M Sach
M Sach

Reputation: 34424

Outcome of this simple java program?

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

Answers (5)

M Sach
M Sach

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

Ted Hopp
Ted Hopp

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

FoolishSeth
FoolishSeth

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

aymankoo
aymankoo

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

Samuel Edwin Ward
Samuel Edwin Ward

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

Related Questions