解決策は、提案するように関数の引数を最終的にすることです。
最終変更子は、最初の割り当て後に参照を再割り当てできないことを意味します。それは参照されるオブジェクトに保証を与えません。
btwこれは、匿名の内部クラスが言語に「埋め込まれた」方法の人為的なものです。コンパイラは各引数の隠しフィールドを作成します。上のコードを逆コンパイルすると、何が起こっているのかを見ることができます。
以下の逆コンパイルでは、新しいクラスFoo $ 1が作成されています(fooメソッド#0) 6行目ではコンストラクタのUser argが渡されます。あなたは、同様のペテンは$ 1.class
が
class Foo$1 extends java.lang.Object implements java.lang.Runnable{
final Foo this$0;
private final User val$user;
Foo$1(Foo, User);
Code:
0: aload_0
1: aload_1
2: putfield #14; //Field this$0:LFoo;
5: aload_0
6: aload_2
7: putfield #16; //Field val$user:LUser;
10: aload_0
11: invokespecial #18; //Method java/lang/Object."<init>":()V
14: return
public void run();
Code:
0: aload_0
1: getfield #14; //Field this$0:LFoo;
4: getfield #26; //Field Foo.nameTextField:Ljavax/swing/JTextField;
7: aload_0
8: getfield #16; //Field val$user:LUser;
11: invokeinterface #32, 1; //InterfaceMethod User.getName:()Ljava/lang/String;
16: invokevirtual #38; //Method javax/swing/JTextField.setText:(Ljava/lang/String;)V
19: return
}
"Foo.java" より作成 "Foo.java"
public class Foo extends java.lang.Object{
protected javax.swing.JTextField nameTextField;
public Foo();
Code:
0: aload_0
1: invokespecial #10; //Method java/lang/Object."<init>":()V
4: return
public void foo(User);
Code:
0: new #18; //class Foo$1
3: dup
4: aload_0
5: aload_1
6: invokespecial #20; //Method Foo$1."<init>":(LFoo;LUser;)V
9: invokestatic #23; //Method java/awt/EventQueue.invokeLater: (Ljava/lang/Runnable;)V
12: return
}
からコンパイルされたため息はFooの逆コンパイルで起こって表示されます
ここに私のFoo.javaがあります(あなたはコンパイルされませんでした...)
import javax.swing.JTextField;
public class Foo {
protected JTextField nameTextField;
public void foo(final User user) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
nameTextField.setText(user.getName());
}
});
}
}