Reputation: 34424
public class NotActuallyImmutable {
private final int x;
public NotActuallyImmutable(int x) {
this.x = x;// line 1
}
public int getX() {
return x;
}
}
public class Mutable extends NotActuallyImmutable {
private int x = 123;
public Mutable(int x) {
super(x);
}
public int getX() {
return x++;
}
}
now in my main class
NotActuallyImmutable n = new Mutable(42); // line2
int x = n.getX();
System.out.println("x is"+x);
I am expecting the output as 42 but it return the output as 123. I am expecting 42 because at line 2 I am making object of class Mutable and then at line 1 I am setting value as 42. so when i do n.getX()
I should get the this latest value not the default 123. I know Ii am missing something but not able to figure out the logic behind it?
Upvotes: 2
Views: 135
Reputation: 34424
I agree with Nice explanations given in above answers. But to to just brief the final understanding. As i am doing new Mutable(42).getX(), jvm first will look in Mutable object to get the value of X not inside NotActuallyImmutable. If i remove getX() method from Mutable , i get the expected(as per my expectation) value i.e 42.
This example gets messy becoz variable name i.e X is same in parent and child class but good for understanding concept
Upvotes: 0
Reputation: 234795
The problem is that the field x
in Mutable
and the field x
in class NotActuallyImmutable
are not the same. The x
that is returned by getX()
is the one in Mutable
(because the getX()
that is invoked is Mutable.getX()
, not NotActuallyImmutable.getX()
).
Note that if you removed the instance field from Mutable
, then you would have a compiler error because NotActuallyImmutable.x
is private to NotActuallyImmutable
and not accessible to any code in Mutable
.
If you made NotActuallyImmutable.x
a protected field, then Mutable.x
would shadow it and you would still have the same behavior. If you removed Mutable.x
in this case, you would still have a compiler error because you were trying to increment a final
field.
If you remove Mutable.getX()
, then the x
that would be returned by getX()
would be NotActuallyImmutable.x
, despite there being another field of the same name in Mutable
.
Upvotes: 2
Reputation: 4021
n
has two different x
values which are visible in different contexts, the parent class's private member variable and the child class's private member variable.
NotActuallyImmutable n = new Mutable(42); // line2
Creates a new Mutable
. Executes parent(x)
which sets the parent class's x
to 42.
int x = n.getX();
n
is a Mutable
instance so this calls Mutable
's getX()
which returns Mutable
's value for x
(123) rather than the parent's.
Upvotes: 0
Reputation: 671
NotActuallyImmutable n = new Mutable(42); // line2
This means you have an object of type NotActuallyImmutable but the instance of created object is Mutable. so in this code your dealing with Mutable object which will return 123. as the number you passed is saved in NotActuallyImmutable not in Mutable,
Upvotes: 1
Reputation: 6675
The private int x
in Mutable
and the private int x
in NotActuallyImmutable
are completely different fields that just have the same name.
This isn't a problem for the compiler because you can't access a private
field from another class. So as far as the compiler is concerned, when you define Mutable
, the x
in NotActuallyImmutable
is invisible and might as well not exist.
It is of course confusing for the programmer. If you rename one of the fields to y
(and the getter method to getY
) the behaviour seems much more intuitive.
Upvotes: 2