Reputation: 93
I am facing one confusion.
Here is my small code snippet
public class Father {
public String x;
public Father() {
this.init();
System.out.println(this);
System.out.println(this.x);
}
protected void init() {
x = "Father";
}
@Override
public String toString() {
return "I'm Father";
}
void ParentclassMethod(){
System.out.println("Parent Class");
}
}
public class Son extends Father {
public String x;
@Override
protected void init() {
System.out.println("Init Called");
x = "Son";
}
@Override
public String toString() {
return "I'm Son";
}
@Override
void ParentclassMethod(){
super.ParentclassMethod();
System.out.println("Child Class");
}
}
public class MainCLass{
public static void main(String[] args){
Son ob = new Son();
}
So when I'm creating a Son's class instance which is inherited from Class Father, so JVM automatically calls Father's class constructor. It creates Son type instance when Father's constructor called otherwise Father's fields wont initialized. So far Good..!
As you can see field x
is derived from Father's class into Son's class.
And my code initializing x
using init()
method.
Then why its showing null.
Its very confusing. Can any one explain ?
Upvotes: 1
Views: 1375
Reputation: 3412
Variables are not polymorphic in Java. Since you re-declared x
inside Son
, this variable will actually be a different x
than the one in Father
. So in the init
method of Son
, you are initializing the Son
's x
, but not the Father
's x
.
On the other hand, your statement System.out.println(this.x);
is inside the Father
class so it only knows about Father
's x
. Since you no longer initialize this variable due to overriding the init
method, the x
in Father
remains null
(the default) and thus it will print null
.
You can fix the problem by removing public String x;
from the Son
class. This will make Father
's x
the only x
, removing the problem.
However, in general, you want to make this variable private
instead of public
. You should also never call a non-final
method in a constructor. It can only introduce bugs. The proper way to initialize it in this case would be to have a constructor with a parameter in Father
:
public class Father {
private String x;
protected Father(String x) {
this.x = x;
System.out.println(this);
System.out.println(this.x);
}
public Father() {
this("Father");
}
// Rest of father's code, without the init method
}
public class Son extends Father {
public Son() {
super("Son");
}
// Rest of son's code, without the init method
}
Upvotes: 2