Top 30 Java Method Overriding MCQ with Answers

Welcome to the Java Method Overriding MCQ Quiz! In this quiz, we have compiled 30 important multiple-choice questions (MCQs) on method overriding in Java to help you strengthen your understanding of this essential object-oriented programming (OOP) concept.

Whether you are a beginner, a student, or a candidate preparing for technical interviews, these questions will help you test your knowledge and improve your Java programming skills.

The quiz covers key concepts of method overriding, along with practical examples and commonly asked interview questions. So, let’s get started and see how well you understand method overriding in Java!

Which of the following rules regarding access modifiers must be obeyed when overriding a method in Java?
class Parent {
    public void display() {
        System.out.println("Parent");
    }
}
class Child extends Parent {
    // Attempting to override with tighter access
    private void display() {
        System.out.println("Child");
    }
}
A. The overriding method can have any access modifier regardless of the parent method.
B. The overriding method must have a more restrictive access modifier than the parent method.
C. The overriding method cannot reduce accessibility and must be at least as accessible as the overridden method.
D. The overriding method must always be declared as public.

The overriding method cannot reduce accessibility and must be at least as accessible as the overridden method.
Explanation:

  • Visibility Rule: Java enforces that an overriding method cannot have a lower access privilege than the method it overrides in the superclass.
  • Access Hierarchy: From most restrictive to least restrictive, access levels are private, default, protected, and public.
  • Compilation Failure: Since the parent method is public, reducing the child method’s visibility to private violates this rule and triggers a compile-time error.
  • Polymorphism Guarantee: Maintaining or expanding accessibility ensures that any code capable of calling the superclass method can safely invoke the overridden implementation through polymorphism.
Consider the following Java code involving method overriding and checked exceptions. What is the result of compiling and running this program?
import java.io.IOException;
class Reader {
    void readData() throws IOException {
        throw new IOException("IO Error");
    }
}
class FileReader extends Reader {
    @Override
    void readData() throws Exception {
        System.out.println("Reading data");
    }
}
public class Main {
    public static void main(String[] args) {
        Reader r = new FileReader();
        try {
            r.readData();
        } catch (IOException e) {
            System.out.println("Caught IOException");
        }
    }
}
A. It compiles successfully and prints “Reading data”
B. Compilation error because an overriding method cannot throw a broader or new checked exception than the overridden method
C. Compilation error because the catch block is unreachable
D. Runtime exception when calling readData()

Compilation error because an overriding method cannot throw a broader or new checked exception than the overridden method
Explanation:

  • Checked Exception Rule: An overriding method can throw the same exception, a subclass exception (narrower), or no exception at all, but it cannot throw a broader or new checked exception.
  • Exception Hierarchy: Exception is a broader checked exception than IOException.
  • Polymorphic Safety: This restriction ensures that callers handling superclass exceptions are not surprised by unexpected broader checked exceptions at runtime.
  • Result: The code fails to compile due to incompatible throws clauses in the method override.
What happens if a subclass attempts to override a method declared as final in its superclass?
class Base {
    final void display() {
        System.out.println("Base final method");
    }
}
class Derived extends Base {
    @Override
    void display() {
        System.out.println("Derived method");
    }
}
public class Main {
    public static void main(String[] args) {
        Base obj = new Derived();
        obj.display();
    }
}
A. It compiles successfully and prints “Derived method”
B. Compilation error because final methods cannot be overridden
C. Runtime exception when calling display()
D. It compiles successfully and prints “Base final method”

Compilation error because final methods cannot be overridden
Explanation:

  • Final Modifier: The final keyword applied to a method prevents any subclass from overriding or modifying its implementation.
  • Design Intent: Developers use final to enforce consistent behavior and secure critical business logic from unintended alterations in inheritance hierarchies.
  • Compilation Result: The Java compiler detects the override attempt on a final method and immediately triggers a compilation error.
Consider the following Java program involving private methods and inheritance. What is the output of this program?
class Parent {
    private void show() {
        System.out.println("Parent private");
    }
    public void display() {
        show();
    }
}
class Child extends Parent {
    // This is method hiding/shadowing, not overriding
    private void show() {
        System.out.println("Child private");
    }
}
public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.display();
    }
}
A. Child private
B. Compilation Error because private methods cannot be redeclared in a subclass
C. Runtime ClassCastException
D. Parent private

Parent private
Explanation:

  • Private Visibility: Private methods are strictly confined to their defining class and are not inherited by subclasses. Therefore, subclasses cannot override them.
  • Method Shadowing: Declaring a method with the same signature in the subclass defines a completely separate, unrelated method unique to the child class rather than overriding the parent’s method.
  • Execution Flow: When obj.display() is called, it executes the display() method defined in Parent. Within Parent, the show() method invoked is bound to Parent‘s private show() method.
  • Output: The program runs successfully and prints “Parent private”.
Consider the following Java program demonstrating covariant return types with method chaining in an inheritance hierarchy. What is the output of this program?
class Shape {
    Shape draw() {
        System.out.println("Drawing Shape");
        return this;
    }
}
class Circle extends Shape {
    @Override
    Circle draw() {
        System.out.println("Drawing Circle");
        return this;
    }
}
public class Main {
    public static void main(String[] args) {
        Shape s = new Circle();
        s.draw();
    }
}
A. Compilation error due to incompatible return types between parent and child methods
B. Runtime ClassCastException when invoking the overridden method
C. It compiles successfully and prints “Drawing Circle”
D. It compiles successfully and prints “Drawing Shape”

It compiles successfully and prints “Drawing Circle”
Explanation:

  • Covariant Return Types: Java allows an overriding method to return a subtype of the return type declared in the superclass method. Since Circle is a subtype of Shape, this override is fully valid.
  • Dynamic Method Dispatch: At runtime, the reference variable s points to an instance of Circle. Polymorphism ensures that the overridden method in the actual object type is executed.
  • Execution Result: The method invocation resolves to Circle.draw(), printing “Drawing Circle” to the console.
Which of the following fundamental rules must be satisfied for a method in a subclass to correctly override a method in its superclass in Java?
class Parent {
    void process(int x) { /* ... */ }
}
class Child extends Parent {
    // Must follow overriding rules
}
A. The subclass method can change the parameter types as long as the return type remains identical.
B. The subclass method must have the exact same method name and parameter type signature as the superclass method.
C. The subclass method must throw broader checked exceptions than the superclass method.
D. The subclass method can reduce access visibility from protected to private.

The subclass method must have the exact same method name and parameter type signature as the superclass method.
Explanation:

  • Method Signature Requirement: True method overriding requires the overriding method in the child class to have an identical name and parameter list (signature) to the method in the parent class. If parameters differ, it results in method overloading instead of overriding.
  • Return Type Flexibility: While parameter types and order must match precisely, Java permits covariant return types where the return type can be a subtype.
  • Access and Exceptions: Overriding methods cannot reduce access visibility or throw broader/new checked exceptions compared to the parent method.
  • Core Concept: Maintaining identical signatures ensures that runtime polymorphism can correctly dispatch calls based on the actual object instance rather than the reference type.
Consider the following Java program demonstrating the distinction between field hiding and method overriding. What is the output of this program?
class Super {
    int value = 10;
    int getValue() {
        return value;
    }
}
class Sub extends Super {
    int value = 20;
    
    @Override
    int getValue() {
        return value;
    }
}
public class Main {
    public static void main(String[] args) {
        Super obj = new Sub();
        System.out.println(obj.value + " " + obj.getValue());
    }
}
A. 20 20
B. 10 10
C. 10 20
D. 20 10

10 20
Explanation:

  • Field Hiding: Instance variables in Java are hidden rather than overridden. Accessing a field via a reference variable (obj.value) is resolved at compile time based on the declared reference type (Super), evaluating to 10.
  • Method Overriding and Dynamic Dispatch: Methods participate in runtime polymorphism. Calling obj.getValue() dispatches dynamically to the overridden implementation in the actual object type (Sub), which returns Sub‘s value field (20).
  • Combined Output: The expression evaluates to printing 10 20 to the console.
Consider the following Java program where an overridden method is invoked from within a superclass constructor. What is the output of this program?
class Super {
    Super() {
        callMe();
    }
    void callMe() {
        System.out.println("Super.callMe()");
    }
}
class Sub extends Super {
    int x = 42;
    
    @Override
    void callMe() {
        System.out.println("Sub.callMe() x = " + x);
    }
}
public class Main {
    public static void main(String[] args) {
        Sub s = new Sub();
    }
}
A. Prints “Sub.callMe() x = 42”
B. Compilation error because overridden methods cannot be called from constructors
C. Prints “Sub.callMe() x = 0”
D. Runtime NullPointerException

Prints “Sub.callMe() x = 0”
Explanation:

  • Constructor Execution Order: When instantiating a subclass object, the superclass constructor executes before the subclass instance fields are initialized.
  • Polymorphism in Constructors: Dynamic method dispatch still applies during constructor execution, so calling callMe() invokes the overridden version in Sub rather than Super.
  • Uninitialized State: At the moment the superclass constructor calls callMe(), Sub‘s instance variable x has not yet been assigned its value of 42 and retains its default primitive value of 0.
  • Best Practice Warning: Calling overridable methods from within constructors is a classic Java pitfall that leads to subtle bugs due to partially initialized state.
What is the purpose of a “bridge method” generated by the Java compiler during method overriding involving generic superclasses?
class Processor<T> {
    public T execute(T input) {
        return input;
    }
}
class StringProcessor extends Processor<String> {
    @Override
    public String execute(String input) {
        return input.toUpperCase();
    }
}
public class Main {
    public static void main(String[] args) {
        Processor<Object> p = new StringProcessor();
        System.out.println(p.execute("test"));
    }
}
A. To allow multiple inheritance of state through default interface methods.
B. To handle runtime polymorphism correctly when a subclass overrides a generic superclass method with a specialized type, resolving type erasure signature mismatches.
C. To automatically convert checked exceptions into unchecked runtime exceptions during method dispatch.
D. To bypass final modifier restrictions on overridden methods in generic hierarchies.

To handle runtime polymorphism correctly when a subclass overrides a generic superclass method with a specialized type, resolving type erasure signature mismatches.
  • Type Erasure: During compilation, generic type parameters like T are erased and replaced with their bounds (or Object), meaning the superclass method signature in bytecode becomes Object execute(Object input).
  • Signature Mismatch: The subclass overrides the method with a specific type (String execute(String input)), which creates a distinct method signature in the compiled bytecode that would otherwise break polymorphic dispatch when referenced via a superclass type.
  • Bridge Method Generation: To resolve this discrepancy, the Java compiler automatically generates a synthetic “bridge method” in the subclass with the erased signature (accepting and returning Object) that delegates the call to the type-safe method.
  • Polymorphism Guarantee: This compiler-generated mechanism ensures that dynamic method dispatch works seamlessly across generic type boundaries without causing AbstractMethodError or runtime class mismatches.
Consider the synchronized modifier in Java method overriding. Which of the following statements is true regarding whether a subclass method inherits or must retain the synchronized modifier from its superclass?
class Base {
    synchronized void process() {
        System.out.println("Base process");
    }
}
class Derived extends Base {
    @Override
    void process() {
        System.out.println("Derived process");
    }
}
public class Main {
    public static void main(String[] args) {
        Base obj = new Derived();
        obj.process();
    }
}
A. The subclass method must also be declared synchronized; otherwise, a compilation error occurs.
B. The synchronized modifier is not part of the method signature, meaning the subclass method does not inherit it and is free to omit or include it.
C. Omission of the synchronized modifier in the subclass triggers a runtime deadlock.
D. The synchronized modifier is automatically inherited and enforced even if omitted in the subclass.

The synchronized modifier is not part of the method signature, meaning the subclass method does not inherit it and is free to omit or include it.
  • Signature Independence: Modifiers like synchronized, native, and strictfp are implementation details and are not part of the method signature.
  • Inheritance Rule: Subclass methods do not automatically inherit these execution modifiers from the overridden superclass method.
  • Thread Safety Impact: Omitting synchronized in the subclass removes intrinsic object-level locking for that specific override, which can lead to race conditions if thread safety is required.
  • Compilation Behavior: The program compiles successfully regardless of whether the subclass retains the modifier.
What happens when a class implements two interfaces that both define a default method with the exact same signature, and the implementing class fails to override that method?
interface InterfaceA {
    default void display() {
        System.out.println("Interface A");
    }
}
interface InterfaceB {
    default void display() {
        System.out.println("Interface B");
    }
}
class MyClass implements InterfaceA, InterfaceB {
    // Missing explicit override of display()
}
public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.display();
    }
}
A. It compiles successfully and defaults to InterfaceA’s implementation at runtime.
B. Compilation error due to inheritance ambiguity regarding competing default methods.
C. Runtime DiamondInheritanceException occurs upon instantiation.
D. It compiles successfully by automatically executing both default methods sequentially.

Compilation error due to inheritance ambiguity regarding competing default methods.
  • Diamond Problem in Interfaces: When a class inherits multiple default methods with identical signatures from unrelated interfaces, Java considers it an ambiguous conflict.
  • Compiler Enforcement: To prevent unpredictable behavior, the Java compiler mandates that the implementing class must explicitly override the conflicting method.
  • Resolution Syntax: The developer can resolve the conflict by overriding the method and explicitly invoking the desired version using the syntax InterfaceName.super.methodName().
Consider the following Java program demonstrating covariant return types with array types. What is the output or behavior of this program?
class Animal {}
class Dog extends Animal {}
class Shelter {
    Animal[] getAnimals() {
        return new Animal[0];
    }
}
class DogShelter extends Shelter {
    @Override
    Dog[] getAnimals() {
        return new Dog[0];
    }
}
public class Main {
    public static void main(String[] args) {
        Shelter s = new DogShelter();
        System.out.println(s.getAnimals().getClass().getSimpleName());
    }
}
A. Compilation error because array types cannot be used with covariant return types
B. It compiles successfully and prints “Dog[]”
C. Runtime ArrayStoreException
D. It compiles successfully and prints “Animal[]”

It compiles successfully and prints “Dog[]”
  • Array Covariance: In Java, array types are covariant, meaning if Dog is a subtype of Animal, then Dog[] is considered a subtype of Animal[].
  • Covariant Return Types: Since Java 5, an overriding method is permitted to return a subtype of the return type declared in the superclass method. Because Dog[] is a valid subtype of Animal[], this override compiles successfully.
  • Dynamic Method Dispatch: At runtime, the reference variable s points to a DogShelter instance. Polymorphism executes DogShelter.getAnimals(), returning a Dog[] array.
  • Output: Invoking getClass().getSimpleName() on the returned array object accurately reflects its runtime type as Dog[].
Consider the following basic Java program demonstrating method overriding. What is the output of this program?
class Vehicle {
    void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    void start() {
        System.out.println("Car starts with key");
    }
}
public class Main {
    public static void main(String[] args) {
        Vehicle myVehicle = new Car();
        myVehicle.start();
    }
}
A. Vehicle starts
B. Car starts with key
C. Compilation Error
D. Runtime Exception

Car starts with key
  • Runtime Polymorphism: Although the reference variable myVehicle is of type Vehicle, it holds an instance of the subclass Car.
  • Method Overriding: The start() method is overridden in Car, replacing the superclass behavior.
  • Dynamic Dispatch: Java resolves overridden method calls based on the actual object type at runtime, executing Car‘s version.
  • Output: The program prints “Car starts with key”.
Consider the following Java program where a subclass attempts to override a method with an incompatible return type. What is the result?
class Parent {
    int getValue() {
        return 10;
    }
}
class Child extends Parent {
    @Override
    String getValue() {
        return "10";
    }
}
public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        System.out.println(obj.getValue());
    }
}
A. It compiles successfully and prints “10”
B. Compilation error because String is not compatible or a subtype of int
C. Runtime ClassCastException
D. It compiles successfully and prints 10

Compilation error because String is not compatible or a subtype of int
  • Return Type Rule: An overriding method must specify a return type that is identical to or a covariant subtype of the return type declared in the superclass method.
  • Incompatibility: String is completely unrelated to primitive int in the type hierarchy.
  • Compilation Failure: The Java compiler detects this clash during compilation and generates an error indicating that methods cannot differ solely by return type.
What is the result when a subclass attempts to override an instance method from its superclass with a static method?
class Parent {
    void show() {
        System.out.println("Parent show");
    }
}
class Child extends Parent {
    @Override
    static void show() {
        System.out.println("Child show");
    }
}
public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.show();
    }
}
A. It compiles successfully and prints “Child show” at runtime.
B. Runtime error because static and instance methods cannot coexist in an inheritance tree.
C. Compilation error because an instance method cannot be overridden with a static method.
D. It compiles successfully and prints “Parent show” due to method hiding rules.

Compilation error because an instance method cannot be overridden with a static method.
  • Instance vs Static Conflict: An instance method relies on dynamic dispatch and runtime object types, whereas a static method is bound to the class at compile time.
  • Overriding Rule: Java explicitly prohibits changing an instance method into a static method (or vice versa) during overriding because it breaks polymorphic behavior.
  • Compilation Failure: The compiler flags this modifier incompatibility as an error, preventing the code from building.
Consider the following Java code where a subclass attempts to use a wrapper class as a covariant return type for a method originally returning a primitive type. What is the result?
class Parent {
    int getValue() {
        return 10;
    }
}
class Child extends Parent {
    @Override
    Integer getValue() {
        return 20;
    }
}
public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        System.out.println(obj.getValue());
    }
}
A. It compiles successfully and prints 20 via autoboxing.
B. Runtime ClassCastException due to primitive-wrapper type mismatch.
C. Compilation error because covariant return types are restricted to reference types and do not support primitive-to-wrapper conversions.
D. It compiles successfully and prints 10.

Compilation error because covariant return types are restricted to reference types and do not support primitive-to-wrapper conversions.
  • Primitive Return Types: Primitive types (like int) and their wrapper classes (like Integer) are distinct types in Java’s type system; wrappers are not considered subclasses of primitives.
  • Covariant Rule: Covariant return types only apply to reference types where the return type is an actual subclass or subtype.
  • Compilation Result: Because the return type signature does not match or qualify as a valid reference subtype, the compiler reports an error.
Analyze the following Java debugging scenario where a developer attempts to override the equals() method in a subclass. What is the output or behavior of this program?
class Point {
    int x, y;
    Point(int x, int y) { this.x = x; this.y = y; }
}
class ColoredPoint extends Point {
    String color;
    ColoredPoint(int x, int y, String color) {
        super(x, y);
        this.color = color;
    }
    // Intended to override equals()
    public boolean equals(ColoredPoint other) {
        if (other == null) return false;
        return this.x == other.x && this.y == other.y && this.color.equals(other.color);
    }
}
public class Main {
    public static void main(String[] args) {
        Point p1 = new ColoredPoint(1, 2, "Red");
        Point p2 = new ColoredPoint(1, 2, "Red");
        System.out.println(p1.equals(p2));
    }
}
A. It prints true because the coordinates and colors match.
B. Compilation error because equals() cannot take a subclass argument.
C. It prints false because the method in ColoredPoint overloads rather than overrides equals(Object), causing the reference-based Object.equals() to execute on Point reference.
D. Runtime ClassCastException during method dispatch.

It prints false because the method in ColoredPoint overloads rather than overrides equals(Object), causing the reference-based Object.equals() to execute on Point reference.
Explanation:

  • Method Signature Mismatch: The equals() method must take an Object parameter to correctly override Object.equals(). Taking ColoredPoint creates an overloaded method instead of an override.
  • Reference Type Resolution: Because variable p1 is declared as type Point, the program invokes the equals(Object) method contract.
  • Fallback Behavior: Since Point inherits Object.equals(), it performs reference comparison using ==, returning false for distinct object instances despite identical field values.
Consider the following Java program involving method overriding and unchecked (runtime) exceptions. What is the result of compiling and running this program?
class Parent {
    void process() {
        System.out.println("Parent process");
    }
}
class Child extends Parent {
    @Override
    void process() throws NullPointerException, ArithmeticException {
        System.out.println("Child process");
    }
}
public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.process();
    }
}
A. Compilation error because overriding methods cannot declare runtime exceptions if the superclass method has no throws clause.
B. Runtime NullPointerException when the method is invoked via polymorphism.
C. It compiles successfully and prints “Child process”.
D. Compilation error due to conflicting checked exception declarations.

It compiles successfully and prints “Child process”.
  • Unchecked Exceptions Rule: The restrictions on throwing checked exceptions in overridden methods do not apply to unchecked exceptions (subclasses of RuntimeException).
  • Throws Declaration: An overriding method is legally permitted to declare any unchecked exceptions in its throws clause, even if the parent method does not declare them.
  • Compilation & Execution: Because NullPointerException and ArithmeticException are runtime exceptions, the code compiles cleanly and executes successfully, printing “Child process”.
Consider the following Java program where an overriding method in a subclass chooses to throw a narrower (subclass) checked exception than the superclass method. What is the result?
import java.io.IOException;
import java.io.FileNotFoundException;
class Reader {
    void readData() throws IOException {
        throw new IOException("General IO Exception");
    }
}
class FileReader extends Reader {
    @Override
    void readData() throws FileNotFoundException {
        throw new FileNotFoundException("File not found");
    }
}
public class Main {
    public static void main(String[] args) {
        Reader obj = new FileReader();
        try {
            obj.readData();
        } catch (IOException e) {
            System.out.println("Caught IO Exception");
        }
    }
}
A. Compilation error because the subclass method must throw the exact same checked exception class declared in the superclass.
B. It compiles successfully and prints “Caught IO Exception”.
C. Runtime exception because FileNotFoundException cannot be assigned to an IOException catch block.
D. Compilation error because FileNotFoundException is a broader exception than IOException.

It compiles successfully and prints “Caught IO Exception”.
  • Checked Exception Overriding Rule: An overriding method is permitted to throw narrower checked exceptions (subclasses) or no checked exceptions at all compared to the superclass method.
  • Exception Hierarchy: FileNotFoundException is a subclass of IOException, making it a narrower, valid exception declaration.
  • Polymorphic Safety: Because any subclass exception can be caught by a catch block handling the superclass exception type, safety is fully preserved.
  • Execution Result: The program compiles cleanly, executes via dynamic dispatch, and prints “Caught IO Exception”.
Consider the following Java program where a superclass method uses a variable-length argument (varargs) and the subclass overrides it using an explicit array type. What is the result?
class Parent {
    void process(String... items) {
        System.out.println("Parent varargs");
    }
}
class Child extends Parent {
    @Override
    void process(String[] items) {
        System.out.println("Child array");
    }
}
public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.process("A", "B");
    }
}
A. Compilation error because the @Override annotation requires identical parameter syntax.
B. Runtime ClassCastException when invoking via parent reference.
C. It compiles successfully because a varargs parameter of type T is represented as an array type T[] in bytecode, making them signature-compatible.
D. Compilation error because varargs methods cannot be overridden in subclasses.

C. It compiles successfully because a varargs parameter of type T is represented as an array type T[] in bytecode, making them signature-compatible.
  • Varargs Representation: In Java bytecode, a varargs parameter (e.g., String...) is compiled as a single-dimension array (e.g., String[]).
  • Signature Compatibility: Because both declarations resolve to the exact same parameter type signature at the bytecode level, an explicit array parameter legally overrides a varargs parameter.
  • Execution Result: The code compiles cleanly and executes successfully via dynamic method dispatch.
Consider the following Java program involving multilevel inheritance and method overriding. What is the output of this program?
class A {
    void show() {
        System.out.println("A");
    }
}
class B extends A {
    @Override
    void show() {
        System.out.println("B");
    }
}
class C extends B {
    // Inherits show() from B without overriding
}
public class Main {
    public static void main(String[] args) {
        A obj = new C();
        obj.show();
    }
}
A. A
B. Compilation error because class C must explicitly override show()
C. B
D. Runtime ClassCastException

B
  • Inheritance of Overridden Methods: Subclasses automatically inherit methods that were overridden by their superclasses. Class C inherits the overridden show() method from B.
  • Dynamic Method Dispatch: At runtime, Java resolves method calls by searching up the inheritance hierarchy starting from the actual object type (C) to find the most specific implementation, which is in B.
  • Output: The program executes successfully and prints “B”.
Consider the following Java scenario where a subclass located in a different package attempts to override a package-private (default access) method from its superclass. What is the result?
// File in package: pkg1
package pkg1;
public class Parent {
    void display() {
        System.out.println("Parent");
    }
}

// File in package: pkg2 (different package)
package pkg2;
import pkg1.Parent;

public class Child extends Parent {
    @Override
    public void display() {
        System.out.println("Child");
    }
}
A. It compiles successfully and prints “Child” when invoked via polymorphism.
B. It compiles successfully and treats the method as a new, distinct method without overriding.
C. Compilation error because the package-private method is not visible in another package, causing the @Override annotation to fail since no superclass method is being overridden.
D. Runtime ClassCastException due to package visibility boundaries.

C. Compilation error because the package-private method is not visible in another package, causing the @Override annotation to fail since no superclass method is being overridden.
  • Package-Private Visibility: Package-private (default) members are strictly restricted to classes within the exact same package and are neither inherited nor visible across package boundaries.
  • Overriding Prerequisite: For a method to be overridden, it must first be visible to the subclass. Because Child in pkg2 cannot see Parent‘s package-private display() method, it cannot override it.
  • Annotation Enforcement: The presence of the @Override annotation instructs the compiler to verify that a superclass method is actively being overridden. Since no visible superclass method matches, the compiler triggers an error.
Consider the following Java program where a class extends a superclass and implements an interface, both defining a method with the exact same signature. The subclass does not explicitly override this method. What is the result?
class SuperClass {
    public void display() {
        System.out.println("SuperClass method");
    }
}
interface MyInterface {
    default void display() {
        System.out.println("Interface default method");
    }
}
class Child extends SuperClass implements MyInterface {
    // No explicit override of display()
}
public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
        obj.display();
    }
}
A. Compilation error due to method ambiguity between the superclass and interface.
B. It compiles successfully and prints “SuperClass method” because class definitions take precedence over interface default methods.
C. It compiles successfully and prints “Interface default method” because interface defaults override class methods.
D. Runtime ClassCastException during method resolution.

It compiles successfully and prints “SuperClass method” because class definitions take precedence over interface default methods.
  • Class Wins Rule: When a class inherits a method with the same signature from both a superclass and an interface default method, the superclass method automatically takes precedence.
  • No Ambiguity Conflict: Unlike multiple interface inheritance where competing default methods cause a compilation error, Java resolves class-versus-interface method collisions deterministically in favor of the class.
  • Output: The program compiles cleanly and prints “SuperClass method”.
Consider the following Java program where a subclass defines a method with the same name but uses a wrapper parameter type instead of a primitive. What is the output of this program?
class Base {
    void process(int x) {
        System.out.println("Base int");
    }
}
class Derived extends Base {
    void process(Integer x) {
        System.out.println("Derived Integer");
    }
}
public class Main {
    public static void main(String[] args) {
        Base obj = new Derived();
        obj.process(10);
    }
}
A. Derived Integer
B. Base int
C. Compilation error due to parameter type mismatch
D. Runtime ClassCastException

Base int
  • Overloading vs. Overriding: Changing a parameter type from primitive int to wrapper Integer creates an overloaded method rather than overriding the superclass method.
  • Inheritance: Class Derived inherits process(int) from Base while introducing a separate overloaded method process(Integer).
  • Dispatch Behavior: Because the reference variable obj is of type Base, the compiler and runtime invoke the inherited process(int) method, printing “Base int”.
Consider the following Java program where a subclass defines a method with the exact same name and signature as a private method in its superclass. What is the result when attempting to invoke this method via a superclass reference?
class Parent {
    private void display() {
        System.out.println("Parent private");
    }
}
class Child extends Parent {
    public void display() {
        System.out.println("Child public");
    }
}
public class Main {
    public static void main(String[] args) {
        Parent p = new Child();
        p.display();
    }
}
A. It compiles successfully and prints “Child public” via polymorphism.
B. Compilation error because display() has private access in Parent and is not visible for method invocation through a Parent reference.
C. It compiles successfully and prints “Parent private”.
D. Runtime ClassCastException during dynamic dispatch.

Compilation error because display() has private access in Parent and is not visible for method invocation through a Parent reference.
  • Private Visibility: private members are strictly confined to their defining class and are neither inherited nor visible to subclasses.
  • Independent Methods: The method in Child does not override Parent‘s method; instead, it is an entirely independent, new method.
  • Compile-Time Check: When invoking a method on a reference of type Parent, the compiler checks visibility within Parent. Because display() is private in Parent, the compiler rejects the call with an accessibility error.
Consider a real-world enterprise payment processing system where different payment gateways implement a shared interface or base class. What is the output and behavior of the following payment execution program?
abstract class PaymentProcessor {
    abstract void processPayment(double amount);
}
class StripeProcessor extends PaymentProcessor {
    @Override
    void processPayment(double amount) {
        System.out.println("Processing $" + amount + " securely via Stripe API.");
    }
}
class PayPalProcessor extends PaymentProcessor {
    @Override
    void processPayment(double amount) {
        System.out.println("Processing $" + amount + " securely via PayPal Sandbox.");
    }
}

public class Main {
    public static void executeTransaction(PaymentProcessor processor, double amount) {
        processor.processPayment(amount);
    }
    public static void main(String[] args) {
        PaymentProcessor gateway = new StripeProcessor();
        executeTransaction(gateway, 150.00);
    }
}
A. Compilation error because abstract methods cannot be overridden in subclasses.
B. It compiles successfully and prints “Processing $150.0 securely via Stripe API.” via dynamic method dispatch.
C. Runtime ClassCastException when invoking executeTransaction.
D. It compiles successfully and prints “Processing $150.0 securely via PayPal Sandbox.”

It compiles successfully and prints “Processing $150.0 securely via Stripe API.” via dynamic method dispatch.
  • Polymorphism in Architecture: Real-world payment systems use polymorphic references (PaymentProcessor) so that high-level checkout services can execute transactions without coupling to specific vendor implementations.
  • Dynamic Dispatch: At runtime, Java inspects the actual object reference assigned (StripeProcessor) and routes the method invocation to the correct implementation.
  • Extensibility: New payment vendors can be integrated seamlessly into the codebase by extending the base class and overriding processPayment() without rewriting existing transaction logic.
Consider a real-world enterprise user management module where a data repository subclass leverages **covariant return types** to specialize the return value of a query method. What is the output and behavior of this program?
class BaseRepository {
    public Object findById(long id) {
        return "Generic Record";
    }
}
class UserRepository extends BaseRepository {
    @Override
    public String findById(long id) {
        return "User Profile [ID: " + id + "]";
    }
}
public class Main {
    public static void main(String[] args) {
        BaseRepository repo = new UserRepository();
        System.out.println(repo.findById(101));
    }
}
A. Compilation error because overriding methods cannot change the return type from Object to String.
B. It compiles successfully and prints “User Profile [ID: 101]” via dynamic method dispatch because String is a valid covariant return type of Object.
C. Runtime ClassCastException due to return type widening.
D. It compiles successfully and prints “Generic Record”.

It compiles successfully and prints “User Profile [ID: 101]” via dynamic method dispatch because String is a valid covariant return type of Object.
  • Covariant Return Types: An overriding method is permitted to specify a return type that is a subtype (such as String) of the return type declared in the superclass (such as Object).
  • Dynamic Method Dispatch: At runtime, polymorphism resolves the method call against the actual object instance type (UserRepository), executing the specialized implementation.
  • Real-World Utility: This pattern allows repository layers to return specific domain models or DTOs directly without requiring callers to manually cast generic return types.
Consider the following real-world configuration parser snippet where a subclass attempts to override a method while incorrectly altering checked exception declarations. Which line or rule causes a compilation error?
import java.io.IOException;
import java.sql.SQLException;
class ConfigurationLoader {
    public void loadConfig() throws IOException {
        // Base config loading logic
    }
}
class XMLConfigurationLoader extends ConfigurationLoader {
    @Override
    public void loadConfig() throws SQLException, IOException {
        // XML specific loading logic
    }
}
A. Line 11: The overriding method adds a new checked exception (`SQLException`) that is not declared in the superclass method, violating checked exception overriding rules.
B. Line 11: The `@Override` annotation is invalid because `loadConfig()` returns `void`.
C. Line 4: The superclass method cannot declare checked exceptions.
D. Line 11: Subclasses are prohibited from declaring any checked exceptions if the parent class throws an `IOException`.

Line 11: The overriding method adds a new checked exception (`SQLException`) that is not declared in the superclass method, violating checked exception overriding rules.
  • Checked Exception Overriding Rule: An overriding method cannot throw broader or new checked exceptions that are not subclasses of the exceptions declared in the superclass method.
  • Compilation Failure: Because SQLException is unrelated to and broader than the exception contract established by ConfigurationLoader.loadConfig(), the compiler flags this as an error to preserve caller type safety.
Consider the following real-world UI component framework snippet where a class implements multiple interfaces defining default methods with identical signatures. Which rule causes a compilation error?
interface Renderable {
    default void render() {
        System.out.println("Rendering Renderable component");
    }
}
interface Visual {
    default void render() {
        System.out.println("Rendering Visual component");
    }
}
class Panel implements Renderable, Visual {
    // Missing explicit override implementation
}
A. Line 13: Compilation error because implementing multiple interfaces with the same default method signature creates an inheritance conflict that requires an explicit override in the implementing class.
B. Line 13: It compiles successfully by automatically selecting the first interface listed in the implements clause (`Renderable`).
C. Line 13: Runtime `IncompatibleClassChangeError` when the class is loaded by the JVM.
D. Line 1: Interfaces are prohibited from having default methods if multiple interfaces are implemented simultaneously.

Line 13: Compilation error because implementing multiple interfaces with the same default method signature creates an inheritance conflict that requires an explicit override in the implementing class.
  • Diamond / Multiple Inheritance Conflict: When a class inherits two or more default methods with the exact same signature from unrelated interfaces, Java considers it an ambiguous inheritance conflict.
  • Explicit Resolution Required: The compiler refuses to guess which default implementation to prefer and halts with an error unless the implementing class explicitly resolves the conflict by overriding the method and choosing one (e.g., Renderable.super.render()).
Consider the following real-world data processing pipeline snippet where a class implements a generic interface. What causes a compilation error in this program?
interface DataProcessor<T> {
    T processData(String input);
}
class IntegerDataProcessor implements DataProcessor<Integer> {
    @Override
    public String processData(String input) {
        return input.length() + "";
    }
}
A. Line 6: The return type of the overriding method (`String`) does not match the specialized type argument (`Integer`) defined in the interface implementation clause, causing a return type incompatibility error.
B. Line 1: Generic interfaces are prohibited from declaring parameterized return types.
C. Line 6: The `@Override` annotation is invalid because interface methods cannot be overridden by implementing classes.
D. Line 6: Runtime `ClassCastException` due to generic type erasure.

Line 6: The return type of the overriding method (`String`) does not match the specialized type argument (`Integer`) defined in the interface implementation clause, causing a return type incompatibility error.
  • Generic Type Substitution: When IntegerDataProcessor implements DataProcessor<Integer>, all occurrences of type parameter T inside the interface are replaced with Integer. Therefore, the required method signature becomes Integer processData(String input).
  • Compilation Failure: Because the implementing class defines processData() to return a String instead of an Integer, it fails to fulfill the interface contract, triggering a compilation error.

DEEPAK GUPTA

DEEPAK GUPTA

Deepak Gupta is the Founder of Scientech Easy, a Full Stack Developer, and a passionate coding educator with 8+ years of professional experience in Java, Python, web development, and core computer science subjects. With strong expertise in full-stack development, he provides hands-on training in programming languages and in-demand technologies at the Scientech Easy Institute, Dhanbad.

He regularly publishes in-depth tutorials, practical coding examples, and high-quality learning resources for both beginners and working professionals. Every article is carefully researched, technically reviewed, and regularly updated to ensure accuracy, clarity, and real-world relevance, helping learners build job-ready skills with confidence.