3

According to the following quote, I expect to see overriden nullstackoverflow instead of overriden nullnull. What point did I miss?

Hiding Fields

Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different.

class A {
    public static void main(String[] args) {
        new B("message is here");
    }

    protected int i = 13;
    public void print() { System.out.println("Hello"); }
    public A() { i = 13; print(); }
}

class B extends A {
    private String i = "stackoverflow";
    private String msg;
    public void print() { System.out.println("overriden " + msg + i); }
    public B(String msg) { super();  this.msg = msg; }
}

1 Answers1

3

What point did I miss?

The point that print() is being invoked by the A constructor, and that executes before the field initializer in B is invoked. See JLS 15.9.4 for details of exactly how class instance creation expressions execute.

So yes, it's using the B.i variable, but that variable doesn't yet have the value of stackoverflow. If you were to remove the print() invocation from the constructor and just write new B("message is here").print() then you'd see "overriden nullstackoverflow".

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I don't know why I did not try to debug step-by-step. That is to say, it was time to see your answers (: Thank you. Eid mubarak. The question seems easy but not. Actually `i` is declared but not initialized before calling `super()`, that is, it is the hidden value in the subtype, whose default value is `null`. Upon completion of `super()`, `i` is defined(=assigned) – Soner from The Ottoman Empire May 04 '22 at 17:29
  • @snr: I think it's clearer to say that the field initializer for `i` is executed after `super()`. (That's why I specifically used that terminology in the answer.) – Jon Skeet May 04 '22 at 17:44
  • yes, sir. It is initialized after super() but declared by default value before super(). That is why i can be recognized as hider by default value. – Soner from The Ottoman Empire May 04 '22 at 17:52
  • @snr: I don't really know what you mean by "recognized as hider" but the fact that a field is hidden is independent of when it's initialized. You can tell that you're using the hidden field by just writing `String x = i;` in a method, for example... that wouldn't compile if it was still referring to the `int` field. – Jon Skeet May 04 '22 at 18:20
  • I mean the value which is in subclass hides the value which is in super class. The subclass’ instance variable(=hider) is of default value which is null for String. It has null value when it is declared. It has user defined value when initialized after super() call is finished. – Soner from The Ottoman Empire May 04 '22 at 19:01
  • @snr: I wouldn't think about one *value* hiding another, but one *field* - that keeps you in line with how the spec describes things. At that point, there are two *entirely separate* things in your question: 1) field hiding; 2) field initialization. You would see exactly the same result if you used a different variable name in `B`, showing that your previous confusion really wasn't about field hiding, but about field initialization. – Jon Skeet May 05 '22 at 05:31
  • 1
    You can also tell that the subclass’s field has been used by the mere fact that reading the superclass’s ̀`int` field can never result in `null`. By the way, the result would be different if `B.i` was declared `final`. – Holger May 06 '22 at 09:27