我有一个匿名类需要在创建时使用自引用。我的业务代码可以简化为以下代码,我知道这段代码:
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();
答案 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
}
};