Как слушатель события Java, определенный как анонимный внутренний класс, может использовать переменную из включающего класса? - PullRequest
2 голосов
/ 20 июля 2010

Вот код:

protected Dialog onCreateDialog(int id) {
    Dialog dialog = null;
    if (id == DIALOG_SEARCH) {
        dialog = new Dialog(this);
        dialog.setContentView(R.layout.search_dialog_layout);
        dialog.setTitle("Search Dialog");
        Button button = (Button) dialog.findViewById(R.id.Button01);
        final Button button2 = (Button) dialog.findViewById(R.id.Button02);
        button2.setEnabled(false);
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                button2.setEnabled(true);
            }
        });
    }
    return dialog;
}

Как анонимный внутренний класс (OnClickListener) имеет доступ к переменной button2?Его метод onClick вызывается в случайное время в будущем при нажатии button.В каком контексте работает эта функция?Как он узнал о button2?Я просто запутался по поводу объема и контекста здесь.

Ответы [ 3 ]

2 голосов
/ 20 июля 2010

Часто лучший способ узнать, как компилятор Java что-то делает, - это скомпилировать класс и затем запустить его через Jad (JAva Decompiler).В этом случае создается впечатление, что javac просто создает дополнительную переменную в анонимном внутреннем классе с именем «val $ o» и инициализирует ее в статическом инициализаторе.Видя это преобразование, становится понятнее, почему Java требует, чтобы вы сделали переменную final, прежде чем использовать ее в анонимном внутреннем классе.Без требования две переменные могут иметь разные значения во время выполнения.Кроме того, это на самом деле ничем не отличается от механизма, который Java использует, чтобы разрешить всем внутренним классам (анонимным или именованным) доступ к содержащему их классу.Вы можете видеть, что внутренний класс содержит ссылку на переменную this этого класса с именем "this $ 0".

Я скомпилировал более простой пример:

public class Outer {

    public void outerMethod() {
        final Object o = "fromOuter";
        new Object() {
            public void innerMethod() {
                System.out.println(o);
            }
        }.innerMethod();
    }
}

и получил это от другогоконец:

public class Outer {

    public Outer()
    {
    }

    public void outerMethod()
    {
        final Object o = "fromOuter";
        (new Object() {

            public void innerMethod()
            {
                System.out.println(o);
            }

            final Outer this$0;
            private final Object val$o;


            {
                this$0 = Outer.this;
                o = obj;
                super();
            }
        }).innerMethod();
    }
}
1 голос
/ 20 июля 2010

Любой созданный вами анонимный класс сохранит ссылку на включающий класс, который позволит им получить доступ к переменным во внешнем классе.

1 голос
/ 20 июля 2010

Здесь есть довольно подробное объяснение: http://renaud.waldura.com/doc/java/final-keyword.shtml#vars

...