Il n'y aura pas de différence entre les deux. Les deux sont convertis au moment de la compilation en fichiers de classe, qui peuvent être exécutés de la même manière que n'importe quelle autre classe, sans avoir besoin de recompiler ou de redéfinir quoi que ce soit dans la boucle.
Cependant, il existe une légère différence dans certains cas, ce qui peut rendre une classe interne légèrement plus efficace (bien qu'elle puisse être éliminée par le JIT). La classe anonyme sera compilée comme une classe non statique si elle est faite à l'intérieur d'une méthode d'instance, donc quand elle est construite, elle doit copier la référence this
de sa classe contenant, qui ajoute quelques instructions de bytecode. Ce sera cependant un surcoût négligeable.
Pour le démontrer, j'ai écrit ce petit programme:
public class Test{
public void test(){
new Runnable(){
public void run(){
System.out.println("Anon");
}
}.run();
new Inner().run();
}
class Inner implements Runnable{
public void run(){
System.out.println("Inner");
}
}
static class Static implements Runnable{
public void run(){
System.out.println("Static");
}
}
}
Et voici le bytecode mis par les différentes classes:
Test:
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void test();
Code:
0: new #2 // class Test$1
3: dup
4: aload_0
5: invokespecial #3 // Method Test$1."<init>":(LTest;)V
8: invokevirtual #4 // Method Test$1.run:()V
11: new #5 // class Test$Inner
14: dup
15: aload_0
16: invokespecial #6 // Method Test$Inner."<init>":(LTest;)V
19: invokevirtual #7 // Method Test$Inner.run:()V
22: return
}
Test 1 $ (l'anonyme classe):
class Test$1 implements java.lang.Runnable {
final Test this$0;
Test$1(Test);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LTest;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: return
public void run();
Code:
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String Anon
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
test $ intérieure (la classe interne):
class Test$Inner implements java.lang.Runnable {
final Test this$0;
Test$Inner(Test);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LTest;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: return
public void run();
Code:
0: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #4 // String Inner
5: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
test $ statique (la classe interne statique):
class Test$Static implements java.lang.Runnable {
Test$Static();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void run();
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Static
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
En regardant cela, vous pouvez voir que la seule différence est que la La classe statique a un constructeur légèrement plus petit.
semble que nous avons écrit la même chose à peu près en même temps :-) – tucuxi
@tucuxi Oui.Je vous ai donné un upvote, car j'avais complètement raté que la classe anonyme était statique dans ce cas: P – resueman