Today we’ll look into a rare feature of Java: variable shadowing
First, let’s define what is a shadowed field or method:
A field is considered shadowed when
- a subclass of its declaring class declares a field with the same name
- a variable having the same name and type is declared in the local scope
- a method argument/parameter is declared with the same name and type
Local variable shadowing
public class MyClass
{
private int count = 10;
private void localVariable()
{
int count = 5;
System.out.println("count = "+ count);
}
public static void main(String[] args)
{
MyClass test = new MyClass();
test.localVariable();
}
}
The above code will output
count = 5
because the count local variable declared at line 7 shadows the variable count declared at the class level. If we want to access the instance variable, we need to add this keyword.
private void localVariable()
{
int count = 5;
System.out.println("count = "+ this.count);
}
Method argument shadowing
This situation is very common even though we do not pay much attention to it. Below is a simple getter definition
private int count;
public void setCount(int count)
{
this.count = count;
}
This keyword is mandatory to resolve the ambiguity. Without this, the compiler cannot know whether we are assigning the count method argument value to itself. If you remove this keyword, you would get a compilation warning anyway.
Superclass field shadowing
Let’s consider the following classes:
public class SuperClass
{
protected String val = "SUPER_VAL";
protected void display()
{
System.out.println("val = "+this.val);
}
}
public class ChildClass extends SuperClass
{
private String val;
public ChildClass(String value) {
this.val = value;
}
public static void main(String[] args)
{
ChildClass child = new ChildClass("CHILD_VAL");
child.display();
}
}
The execution gives:
val = SUPER_VAL
The val field has been declared in the SuperClass but is shadowed in the ChildClass because the latter declares another field with the same name and type. Although the ChildClass has been instantiated with “CHILD_VAL”, the execution of child.display() gives you “SUPER_VAL”.
The reason is simple. When the child instance is created, there are 2 variables val. The one from SuperClass with value “SUPER_VAL” and the one from ChildClass with injected value “CHILD_VAL” through a constructor.
When the display() method is called, since it is defined in the SuperClass, it is the val field in the context of SuperClass which is used. Not surprising that the output shows “SUPER_VAL”.
public class ChildClass extends SuperClass
{
private String val;
public ChildClass(String value) {
this.val = value;
super.val = value;
}
public static void main(String[] args)
{
ChildClass child = new ChildClass("CHILD_VAL");
child.display();
}
}
In the above-modified code, we force the value for the hidden val field in SuperClass with super.val = value and the output gives:
val = CHILD_VAL
Now let’s add another class to the hierarchy
public class AncestorClass
{
protected String val = "ANCESTOR_VAL";
}
public class SuperClass extends AncestorClass
{
protected String val = "SUPER_VAL";
}
public class ChildClass extends SuperClass
{
private String val = "CHILD_VAL";
public void displayVal()
{
System.out.println("val = " + super.val);
}
public static void main(String[] args)
{
ChildClass child = new ChildClass();
child.displayVal();
}
}
Obviously, the output will display
val = SUPER_VAL
The question now is: what if we want to display the val value of ancestor class? Obviously, the super keyword-only refers to the first parent class up in the class hierarchy.
The casting comes to the rescue. Indeed we can force this keyword representing the current class instance to a particular type in the class hierarchy!
public class ChildClass extends SuperClass
{
private String val = "CHILD_VAL";
public void displayVal()
{
System.out.println("val = " + ((AncestorClass) this).val);
}
public static void main(String[] args)
{
ChildClass child = new ChildClass();
child.displayVal();
}
}
This time, we do have
val = ANCESTOR_VAL
nice artical
Worth to read . Thanks