如果Base构造函数调用Derived中的方法重写并且方法使用同名(阴影)字段,究竟会发生什么?

时间:2017-06-28 10:21:34

标签: java inheritance constructor

请验证我的理解/猜测,为什么以下代码会引发NPE以及究竟发生了什么:

  1. 在Derived类的新Derived()构造函数之后调用。
  2. 派生的构造函数立即调用Base构造函数(隐式构造函数链接发生)
  3. 基础构造函数调用foobar()。没有不同的foobar()方法(基本版本和派生版本),所以这是"版本"中的foobar()。在Derived中被覆盖。
  4. 这个foobar()"版本" (在Base \ Derived之间共享)搜索要使用的str字段。由于在Derived中覆盖foobar()("定义"),它需要来自Derived的str(它不能使用来自Base的str)。
  5. 此时,Derived中的str不是init(因为在Base构造函数完成之前,Derived构造函数无法启动),所以我们得到了NPE。
  6. P.S。我知道不建议从构造函数中调用非final或非私有的非静态方法。此外,对于C ++中的虚方法,它在Derived中的重写版本不会像在Java中一样在Base构造函数中调用。

    class Base {
        String str = "abc";
    
        Base() {
            foobar();
        }
    
        void foobar() {
            System.out.println(str.toUpperCase());
        }
    }
    
    class Derived extends Base {
        String str = "qwe";
    
        Derived() {
            foobar();
        }
    
        @Override
        void foobar() {
            System.out.println(str.toLowerCase());
        }
    }
    
    public class My {
    
        public static void main(String[] args) {
            new Derived();
        }
    }
    

    我自己的研究表明,在那些答案中没有相同的(阴影)字段变量(str),这增加了混乱。 answer1 answer2

0 个答案:

没有答案