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

Java 此代码中是否存在任何额外的NullPointerException风险?,java,inner-classes,Java,Inner Classes,我有一个匿名类,创建时需要使用自引用。我的业务代码可以简化为以下代码,我知道此代码: final Runnable runnable=new Runnable() { @Override public void run() { if(Math.random()>0.5){ runnable.run(); } } }; runnable.run(); 无法编译,因为在整个语句完成之前捕获了内部类中runnabl

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

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();
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();
    }
}

您试图捕获的行为几乎肯定应该使用while循环来完成。

如果您想将其放在一个方法中,它不是有效的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();
    }
}
然后它将编译,并且永远不会抛出
NullPointerException
,因为捕获的不是引用的值,而是实际字段(字节码每次都将访问
this.runnable.run()


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

仅供参考,您还可以用
Lambda表达式替换内部类

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

你想完成什么?如果您只想从
runnable()
上调用的实例内方法调用
runnable.run()
,那么只需调用
run()
。不过,这个代码很奇怪。每次调用基本上都有50/50的机会接近堆栈溢出,并且它不会完成任何其他事情。但是这种行为是确定性的,你可以试试看它是否有效。