Rules for Polymorphism

About

Polymorphism in Java is governed by a set of rules that vary depending on whether it is compile-time (method overloading) or runtime (method overriding). Below is a consolidated set of rules for both types.

Rules for Compile-Time Polymorphism (Method Overloading)

Rule

Example

Valid / Invalid

Reason

Same method name

void print() {} void print(String msg) {}

Valid

Overloaded methods must share the same name.

Different parameter list

void sum(int a, int b) {} void sum(double a, double b) {}

Valid

Changing type/number/order of parameters allows overloading.

Return type alone not enough

int getData() {} String getData() {}

Invalid

Compiler cannot differentiate only by return type.

Different access modifiers allowed

public void show(int x) {} private void show(String y) {}

Valid

Access modifiers do not affect method signature.

Different exceptions allowed

void read() throws IOException {} void read(String s) throws SQLException {}

Valid

Exception type does not affect overloading.

Inheritance overloading

class Parent { void show(int x) {} } class Child extends Parent { void show(double x) {} }

Valid

Overloading works across parent-child classes if parameters differ.

Varargs overloading

void display(String... items) {} void display(String item) {}

Valid

Varargs can overload fixed parameters, but must be last.

Static / final methods can be overloaded

static void log(int x) {} static void log(String y) {}

Valid

Static/final methods are still matched at compile time.

Compile-time resolution

public class Problem1 {

    static void test(int x) {
        System.out.println("x");
    }

    static void test(long y) {
        System.out.println("y");
    }

    public static void main(String[] args) {
        test(5); //x
        test(5L); //y
    }

}

Valid

Compiler picks best match based on argument type.

Ambiguity causes compile error

public static void main(String[] args) {
    doSomething(5, 5); // Ambiguous method call. Both error
}

static void doSomething(int x, long y) {
    System.out.println("x");
}

static void doSomething(long x, int y) {
    System.out.println("y");
}

Invalid

Compiler cannot decide; both match equally well.

Rules for Runtime Polymorphism (Method Overriding)

Rule

Example

Valid / Invalid

Reason

Must be in inheritance hierarchy

class Parent { void show() {} } class Child extends Parent { void show() {} }

Valid

Overriding requires a parent-child relationship.

Same method signature

void display(int x) in Parent and Child

Valid

Method name, parameters, and order must match exactly.

Return type must be same or covariant

Parent: Object getData() Child: String getData()

Valid

Covariant return types allowed (narrower type in subclass).

Access level cannot be more restrictive

Parent: public void show() Child: protected void show()

Invalid

Cannot reduce visibility in overriding method.

Can increase access level

Parent: protected void show() Child: public void show()

Valid

Visibility can be widened in overriding method.

Cannot override static methods

Parent: static void print() Child: static void print()

Invalid (this is hiding, not overriding)

Static methods belong to the class, not object.

Cannot override final methods

Parent: final void show()

Invalid

Final methods cannot be changed in subclass.

Cannot override private methods

Parent: private void secret()

Invalid

Private methods are not inherited.

Overridden method can throw fewer/narrower checked exceptions

Parent: void read() throws IOException Child: void read()

Valid

Checked exceptions can be reduced or removed.

Dynamic method dispatch occurs at runtime

Parent p = new Child(); p.show();

Valid

JVM decides which method to call based on object type, not reference type.

Last updated