【问题标题】:Variable is null at super call超级调用时变量为空
【发布时间】:2014-06-20 12:57:08
【问题描述】:

我正在使用 Java 7 并获得了 3 个类:

TestSuper.java

public abstract class TestSuper {
    public TestSuper() {
            testMethod();
    }

    protected abstract void testMethod();
}

TestNull.java

public class TestNull extends TestSuper {
    private String test = "Test";

    public TestNull() {
            super();
            System.out.println(test);
    }

    @Override
    protected void testMethod() {
            System.out.println(test);
    }

}

TestMain.java

public class TestMain {
    public static void main(String[] args) {
            new TestNull();
    }
}

输出:

null
Test

为什么会发生这种情况,有没有好的解决方法?

【问题讨论】:

    标签: java nullpointerexception null superclass super


    【解决方案1】:

    当您调用new TestNull(); 时,您正在调用类TestNull 的构造函数,它调用super() 构造函数:它包含对在TestNull 中实现的方法的调用,您可以在其中打印字符串字段,此时子类TestNull的字段还没有初始化,即为null。

    在超级构造函数调用之后,所有的字段都将被初始化,因此第二次打印实际上显示了(初始化的)字符串的新值。

    这里的关键是子类的字段在超类实例化之后初始化。

    解决方法?这取决于您想要的确切行为:也许不在超级构造函数中调用抽象方法(即在 TestSuper 类的构造函数中)是有意义的。

    【讨论】:

      【解决方案2】:

      根据JLS 8.1.1.1 Abstract Class

      本身不是抽象的抽象类的子类可能是 实例化,导致为 抽象类,因此,执行 Field Initializers 该类的实例变量。

      【讨论】:

        【解决方案3】:

        您正在构造函数中调用 可覆盖 实例方法(它也调用实例字段,在您的情况下为 private String test = "Test";)。这可能会导致不一致,因为实例没有完全构建。这是一个不好的做法,所以避免它:

        public TestSuper() {
               testMethod();
        }
        

        请阅读此主题:What's wrong with overridable method calls in constructors?

        【讨论】:

          【解决方案4】:

          您可以通过将testMethod() 的调用移至单独的函数来解决此问题

          public abstract class TestSuper {
              public TestSuper() { }
          
              public void callTestMethod(){
                testMethod();
              }
          
              protected abstract void testMethod();
          }
          

          然后在TestNull构造函数上调用callTestMethod()

          public TestNull() {
                super.callTestMethod();
                System.out.println(test);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-12-01
            • 2012-08-16
            • 2015-02-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多