在无限循环中使用匿名与嵌套 class (Java)

Using anonymous vs nested class in an infinite loop (Java)

在无限循环的上下文中哪个更好:匿名 class 还是嵌套 class? 如我所见,如果我们使用匿名 class,它会在每次迭代时重新定义,但使用嵌套 class,我们仍然会创建一个实例,但 class 本身不会重新定义。不确定这是否正确...在这种情况下使用一个与另一个相比有什么优势吗?

public class MainThread {
    public static void main(String[] args){    
        while (true) {
        final int data = rand.nextInt();
        //Runnable task = new MyRunnable(data);
        Runnable task = new Runnable() {
            public void run() {
                printData(data);
            }
        };
        new Thread(task).start();
        }
    }

    private static class MyRunnable implements Runnable {
        private int data;

        MyRunnable(int data){
            this.data = data;
        }

        @Override
        public void run() {
            printData(data);
        }
    }
}

匿名内部 class 不是 "redefined for each call" - 它们应该与内部 class 具有完全相同的开销,除了您的内部 class 是静态的因此避免保留对外部 this 的引用,如果有的话。

如果你编译上面的程序,你会看到生成了几个classes:

MainThread.class
MainThread.class
MainThread$MyRunnable.class

反编译 $1(=你的内部匿名 class)和 $MyRunnable(=你的内部命名 class)表明它们本质上是相同的:

  MainThread(int);
    Code:
       0: aload_0       
       1: iload_1       
       2: putfield      #1                  // Field val$data:I
       5: aload_0       
       6: invokespecial #2                  // Method java/lang/Object."<init>":()V
       9: return        

  public void run();
    Code:
       0: aload_0       
       1: getfield      #1                  // Field val$data:I
       4: invokestatic  #3                  // Method MainThread.printData:(I)V
       7: return        

class MainThread$MyRunnable implements java.lang.Runnable {
  MainThread$MyRunnable(int);
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0       
       5: iload_1       
       6: putfield      #2                  // Field data:I
       9: return        

  public void run();
    Code:
       0: aload_0       
       1: getfield      #2                  // Field data:I
       4: invokestatic  #3                  // Method MainThread.printData:(I)V
       7: return        
}

唯一的区别是匿名内部 class 没有在其构造函数中存储 'data',而是从外部静态最终变量中读取它。