最终本地变量可能尚未在匿名内部类中初始化

时间:2012-04-20 01:26:51

标签: java callback anonymous-types final

这是我的代码:

final Foo myFoo = new Foo(new Inner() {
    @Override
    callback(){
         myFoo.bar();
    }
});

(使用实际的功能名称)

final MyArrayAdapter aa = new MyArrayAdapter(new View.OnClickListener() {
    @Override
    onClick(){
         aa.notifyDataSetChanged();
    }
});

Java给我一个关于如何初始化myFoo的错误。有没有什么办法解决这一问题?我可以在构造对象时将回调设置为null,然后在之后进行更改,但我希望有更清洁的方法。有任何想法吗? (如果Foo不是由我编写的,并且之后没有公开接口来更改回调,那么这也行不通)

如果有人好奇,在我的特定场景中,Foo是一个ArrayAdapter,而bar是notifyDataSetChanged()。适配器显示的内容取决于数组中项目的值,并且这些值在单击时会更改。回调是clickListener。

3 个答案:

答案 0 :(得分:6)

简短的回答是你绝对不能用Java做到这一点,但编译器已经告诉你了。你试图一次创建两个对象并引用彼此,这是鸡和蛋的问题。最重要的是,你必须先创建其中一个。

建议是两步创作:

....
final MyArrayAdapter aa = new MyArrayAdapter();
aa.initializeButtonClickListener();
....

然后将'initialize'方法添加到适配器。

public void initializeButtonClickListener(){
    this.button.setOnClickListener(new View.OnClickListener() {
        @Override
        onClick(){
             notifyDataSetChanged();
        }
    });
}

因为这种构造有点复杂(即,比简单地调用构造函数更复杂),我建议然后将这两行拉入MyArrayAdapter工厂方法,并使构造函数变为私有。

答案 1 :(得分:3)

这将在一般情况下工作,无法访问Inner定义,但您需要创建一个帮助程序类:

class CallbackHelper {
    private Foo foo;
    public void setFoo( Foo f ){ foo = f; }
    public Foo getFoo(){ return foo; }
}

然后像这样使用它:

final CallbackHelper cbh = new CallbackHelper();
Foo myFoo = new Foo(new Inner() {
    @Override
    callback(){
         cbh.getFoo().bar();
    }
});
cbh.setFoo( myFoo );

答案 2 :(得分:0)

您可以在包含的类中声明方法callBarOnMyFoo并从回调中调用它:

void callBarOnMyFoo() {
    myFoo.bar();
}

然后你的回调需要调用callBarOnMyFoo,这是外部类的实例方法,Inner代码应该引用它(我忘记了它的语法)。 / p>