5 Java concepts explained: Overloading, overriding, shadowing, hiding, and obscuring

All five concepts are related to using the same name for different things.

Overloading

Methods in the same class with the same name are called overloaded.

Example:

class C { void m ( String s ) { System . out . println ( "String: " + s ); } void m ( int i ) { System . out . println ( "int: " + i ); } }

This is ok as long as the methods differs in arity or type of formal parameters. Which method is called is determined by the compile time types of the arguments.

Real world example: There are 5 different versions of Math.abs .

Overriding

Overriding has to do with inheritance. If Dog extends Animal , then method Dog.eat() overrides Animal.eat() .

Example:

class Animal { void eat () { System . out . println ( "Animal eating" ); } } class Dog extends Animal { @ Override void eat () { System . out . println ( "Dog eating" ); } }

The @Override annotation is not mandatory but highly recommended.

In Java it's always the runtime type that determines which instance method is invked. So if an Animal variable a refers to a Dog object, a.eat() will invoke the overriding Dog.eat method.

Shadowing

One variable shadows another if they have the same name and are accessible in the same place.

Example:

class C { int i = 0 ; void m() { int i = 1; System. out .println( i Local variable shadows field. ); } }

To access the field in the above example, you need to do this.i . Constructor parameters often shadow fields which is why you frequently see assignments such as this.i = i; .

Other things can be shadowed too. A local class can shadow a top-level class, a method in a local class can shadow a method in the enclosing class, and so on.

Hiding

A field is said to hide all fields with the same name in super classes.

Example:

class Animal { int legs = 2 ; } class Dog extends Animal { int legs Dog.legs hides Animal.legs = 4 ; }

You can use super.legs to access Animal.legs from within the Dog class.

Shadowing refers to scoping and import related clashes as opposed to hiding which refers to inheritance related clashes.

Obscuring

If, for example, a local variable and a class share the same name, the precedence rules may render the class unusable. The class is said to be obscured by the variable.

Example:

class C { void m() { String System = "" ; System . out .println( "Hello World" ); Will not compile. System is obscured by the local variable. } }

The above situation could be resolved by using the fully qualified name java.lang.System , or by statically importing System.out . If we happened to also have variables called java and out , neither of these workarounds would work and it would be impossible to access System.out.println .