如何将定义为匿名内部类的java事件侦听器使用封闭类中的变量?

时间:2010-07-20 15:56:05

标签: java event-handling scope listener inner-classes

以下是代码:

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变量?当点击button时,将在某个随机时间调用其onClick方法。在什么情况下这个功能运行?它如何知道button2?我只是对这里的范围和背景感到困惑。

3 个答案:

答案 0 :(得分:2)

通常,了解Java编译器如何执行某些操作的最佳方法是编译该类,然后通过Jad(JAva Decompiler)运行它。在这种情况下,似乎javac只是在名为“val $ o”的匿名内部类上创建一个额外的变量,并在静态初始化程序中初始化它。看到这种转换,可以更清楚地说明为什么Java要求你在匿名内部类中使用变量之前将变量设为final。如果没有这个要求,这两个变量可能会在运行时以不同的值结束。此外,这与Java用于允许所有内部类(匿名或命名)访问其包含类的机制没有什么不同。您可以看到内部类包含对包含类的此变量的引用,名为“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 :(得分:1)

这里有一个非常详尽的解释:http://renaud.waldura.com/doc/java/final-keyword.shtml#vars

答案 2 :(得分:1)

您创建的任何匿名类都将保留对封闭类的引用,这使得它们可以访问外部类中的变量。