Решение состоит в том, чтобы сделать аргументы функции окончательными, как вы предлагаете.
Последний модификатор означает, что ссылка не может быть переназначена после первого присваивания.Это не дает никаких гарантий в отношении упомянутого объекта.
Кстати, это артефакт того, как анонимные внутренние классы были «вложены» в язык.Компилятор создает скрытые поля для каждого из аргументов. Если вы декомпилируете свой код выше, вы увидите, что происходит ...
В декомпиляции ниже вы увидите, что создан новый класс Foo $ 1 (метод foo #0) и в строке № 6 передается аргумент User в своем конструкторе.Подобные махинации вы увидите в декомпиляции Foo $ 1.class sigh
Скомпилировано из "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.java "
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 (ваш не скомпилирован ...)
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());
}
});
}
}