此代码中是否存在额外的NullPointerException风险?

时间:2017-08-03 04:11:37

标签: java inner-classes

我有一个匿名类需要在创建时使用自引用。我的业务代码可以简化为以下代码,我知道这段代码:

final Runnable runnable=new Runnable() {
    @Override
    public void run() {
        if(Math.random()>0.5){
            runnable.run();
        }
    }
};
runnable.run();

无法编译,因为在整个语句完成之前捕获了内部类中runnable的值。并且我不想使用static或class属性来保存runnable,因为我不想忘记在删除此部分时删除不必要的变量。所以我修改成这个:

final Runnable[] runnable={null};
runnable[0]=new Runnable() {
    @Override
    public void run() {
        if(Math.random()>0.5){
            runnable[0].run();
        }
    }
};
runnable[0].run();

与正常对象创建相比,是否存在额外的NullPointerException风险:

Runnable runnable=new Runnable(){
    @Override
    public void run() {
    }
};
runnable.run();

3 个答案:

答案 0 :(得分:1)

您尝试捕获的行为几乎肯定会使用while循环完成。

答案 1 :(得分:0)

如果你想把它放在一个方法中,那它就不是有效的Java,因为你在初始化之前会访问runnable。所以这不会编译:

public class Main {
    public static void main(String[] args) {
        final Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if(Math.random() > 0.5) {
                    runnable.run(); // <-- compilation error here
                }
            }
        };
        runnable.run();
    }
}

但是如果你的意思是在类级别创建它:

public class Main {
    final static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if(Math.random()>0.5){
                runnable.run();
            }
        }
    };
    public static void main(String[] args) {
        runnable.run();
    }
}

然后它将编译并且永远不会抛出NullPointerException因为捕获的不是引用的值而是实际的字段(字节码将分别访问this.runnable.run()时间)。

尽管如此,正如其他人指出的那样,这可以通过while循环完成。

答案 2 :(得分:0)

仅供参考,你也可以用Lambda expression替换你的内部类。

Runnable runnable = ()->{
            if(Math.random()>.5) {
                //TODO Code
            }
        };