2

This question is inspired by this other one I stumbled upon.

Given the following code:

public class Test {

    public static void main(String[] args) {
        Derived b = new Derived();
        Base a = b;

        System.out.println("b.i -> " + b.i);
        System.out.println("a.i -> " + a.i);
        System.out.println("b.getI() -> " + b.getI());
        System.out.println("a.getI() -> " + a.getI());
    }
}

class Base {
    int i = 1;

    public int getI() {
        return i;
    }
}

class Derived extends Base {
    int i = 2;

    public int getI() {
        return -i;
    }
}

// Output:
// b.i -> 2
// a.i -> 1
// b.getI() -> -2
// a.getI() -> -2

Could someone explain why a.i is returning 1? Shouldn't it be accessing i field in Derived class?

In addition, when debugging the code, I can see something like this:

Debug screenshot

There you can see that Derived class is storing a reference to Base.i.

Why is this happening? Shouldn't Base.i be inherited and overwritten by Derived.i?

beni0888
  • 1,050
  • 1
  • 12
  • 40

3 Answers3

2

You've came across the feature of Java called variable Hiding. The field "i" in Derived hides the field "i" in class Base.

Unlike methods, the fields cannot be overridden in java, hence the behavior.

I've found a very in-depth tutorial on this topic that you might consider useful

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
1

According to https://stackoverflow.com/a/41379556/3605497 there is no field polymorphism in Java. This means that the field in the subclass is simply hiding the field in the superclass, and not overloading it.

Tripp Kinetics
  • 5,178
  • 2
  • 23
  • 37
1

After some deeper googling, I eventually found the answer to this question here.

The point is that member variables cannot be overridden like methods, they are just hidden, and upcasting allows to access the hidden method in the base class.

beni0888
  • 1,050
  • 1
  • 12
  • 40