Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)

Overloading, overriding and method hiding (Java)

An overview of how overloading, overriding and method hiding works in Java

Overloading

What it is: a class has several methods with the same name but different number or types of parameters and Java chooses which one to call based on the arguments you pass

class OverloadingTest {
public void testMethod(Object object) {
System.out.println("object");
}
public void testMethod(String string) {
System.out.println("string");
}
}
OverloadingTest test = new OverloadingTest();
Object testObject = new Object();
String testString = "testString";
test.testMethod(testObject); // object
test.testMethod(testString); // string

Important: the exact signature of the method to call is based at compile time using the compile-time types of the arguments

Object testStringAsObject = testString;
test.testMethod(testStringAsObject); // object

Overriding

What it is: a subclass overrides an instance method of a direct or indirect superclass by providing its own implementation

class OverridingTestSuper {
public void testMethod(Object object) {
System.out.println("super");
}
}
class OverridingTestSub extends OverridingTestSuper {
@Override
public void testMethod(Object object) {
System.out.println("sub");
}
}

Note: use@Override annotation when overriding, so the Java compiler helps you check that the method is actually correctly overriding a supertype method

OverridingTestSuper testSuper = new OverridingTestSuper();
OverridingTestSub testSub = new OverridingTestSub();
Object testObject = new Object();
testSuper.testMethod(testObject); // super
testSub.testMethod(testObject); // sub

Important: The implementation to invoke is determined at run time based on the actual runtime type of the object and the structure of the inheritance hierarchy

OverridingTestSuper testSubAsSuper = testSub;
testSubAsSuper.testMethod(testObject); // sub

Combining overloading and overriding

class CombinedTestSuper {
public void testMethod(Object object) {
System.out.println("super object");
}
}
class CombinedTestSub extends CombinedTestSuper {
@Override
public void testMethod(Object object) {
System.out.println("sub object");
}
public void testMethod(String string) {
System.out.println("sub string");
}
}
CombinedTestSuper testSuper = new CombinedTestSuper();
CombinedTestSub testSub = new CombinedTestSub();
CombinedTestSuper testSubAsSuper = testSub;
String testString = "testString";
Object testStringAsObject = testString;
testSuper.testMethod(testString); // super object (only one method on CombinedTestSuper)
testSuper.testMethod(testStringAsObject); // super object (only one method on CombinedTestSuper)
testSub.testMethod(testString); // sub string (chooses signature testMethod(String) on CombinedTestSub)
testSub.testMethod(testStringAsObject); // sub object (chooses signature testMethod(Object) on CombinedTestSub)
testSubAsSuper.testMethod(testString); // sub object (uses signature of only method on CombinedTestSuper but implementation of CombinedTestSub)
testSubAsSuper.testMethod(testStringAsObject); // sub object (uses signature of only method on CombinedTestSuper but implementation of CombinedTestSub)

Method hiding

For static methods, overloading is still used to determine the signature of the method to invoke

But what if superclass and subclass both have static method with same signature?

class CombinedTestSuper {
public static void testStaticMethod(Object object) {
System.out.println("super");
}
}
class CombinedTestSub extends CombinedTestSuper {
public static void testStaticMethod(Object object) {
System.out.println("sub");
}
}

Calling static methods on classes:

Object testObject = new Object();
StaticSuper.testStaticMethod(testObject); // super
StaticSub.testStaticMethod(testObject); // sub

Calling static methods on instances (note that this will generate compiler warnings):

StaticSuper staticSuper = new StaticSuper();
StaticSub staticSub = new StaticSub();
StaticSuper staticSubAsSuper = staticSub;
staticSuper.testStaticMethod(testObject); // super
staticSub.testStaticMethod(testObject); // sub
staticSubAsSuper.testStaticMethod(testObject); // super (!!!)

No overriding here! Instead, we get method hiding.

Can be pretty confusing (not only the method hiding itself, but also the fact that we call a static method in a way that makes it look like an instance method), which is also why we get warnings when doing this.

Resources