带有覆盖方法的NullPointerException

dan*_*nez 2 java

任何人都可以评论他们对解决以下问题的最佳方法的看法吗?我已经尝试了init块并在构造函数中初始化了字段,但是在重写方法尝试清除它之前都没有调用它.

 class TestRunner {
        public static void main(String[] args) {
            ftw ftw = new ftw();
            ftw.dontPanic();
        }
    }

    class wtf {

        wtf(){
            this.dontPanic();
        }

        void dontPanic() {
            System.out.println("super don't panic");
        }
    }

    class ftw extends wtf {
        final HashSet variableOfDoom = new HashSet();

        ftw(){
            super();
        }

        void dontPanic() {
            super.dontPanic();
            System.out.println("sub don't panic");
            variableOfDoom.clear(); //This line prints a null pointer exception, because the field hasn't been intialized yet.
        }
    }
Run Code Online (Sandbox Code Playgroud)

Han*_*Gay 7

这就是为什么他们建议你不要final在构造函数中调用非方法.private方法也是安全的,因为它们不能被覆盖.

假设您无法遵循该声音建议,出于某种原因,这里有一些其他可能有用的观察结果:

  • 我假设你为了这个例子而简化了,但是调用.clear()并没有真正完成示例中的任何事情; 你可以删除它.
  • 很难说没有看到实际的程序,但是你可以通过将变量赋值为new HashSet而不是调用来滑冰.clear().

  • 这是一个链接:http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-superclass-constructor/更有权威性来自Effective Java的引用:**构造函数不得直接或间接调用可覆盖的方法**.(第1版,第80页,第15项:继承的设计和文件或禁止它) (3认同)

Mic*_*ers 7

这是问题所在:您的执行流程如下所示:

main
->ftw()
  ->wtf()
    ->wtf.dontPanic()
Run Code Online (Sandbox Code Playgroud)

但是由于方法调用是在运行时在Java中确定的,ftw.dontPanic()因此实际上是调用方法.并且variableOfDoom在构造函数完成之前不会设置,但构造函数将永远不会因异常而完成.

解决方案不是在构造函数中工作(至少不使用private非非final方法).