简体   繁体   English

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

[英]Final Local Variable may not have been initialized in anonymous inner class

Here is my code: 这是我的代码:

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

(With actual function names) (带实际功能名称)

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

Java is giving me an error about how myFoo might not have been initialized. Java给我一个关于如何初始化myFoo的错误。 Is there any way to fix this? 有没有什么办法解决这一问题? I can potentially set the callback to null when I construct the object and then change it afterwards, but I'd hope for there to be a cleaner way. 我可以在构造对象时将回调设置为null,然后在之后进行更改,但我希望有更清洁的方法。 Any ideas? 有任何想法吗? (Also that wouldn't work if Foo wasn't written by me and didn't expose an interface to change the callback later) (如果Foo不是由我编写的,并且没有公开接口以便稍后更改回调,那么这也行不通)

In case anyone is curious, in my specific scenario, Foo is an ArrayAdapter, and the bar is notifyDataSetChanged(). 如果有人好奇,在我的特定场景中,Foo是一个ArrayAdapter,条形图是notifyDataSetChanged()。 What is displayed by the adapter depends on the values of the items in the array, and those values change when they are clicked on. 适配器显示的内容取决于数组中项目的值,并且这些值在单击时会更改。 The callback is the clickListener. 回调是clickListener。

Short answer is that you definitely can't do that in Java, but the compiler already told you that. 简短的回答是你绝对不能用Java做到这一点,但编译器已经告诉过你了。 You're trying to create two objects at once with references to each other, it's a chicken and egg problem. 你试图一次创建两个对象并引用彼此,这是鸡和蛋的问题。 Bottom line, you have to create ONE of them first. 最重要的是,你必须先创建其中一个。

A suggestion is a two step creation: 建议是两步创建:

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

and then add the 'initialize' method to the adapter. 然后将“initialize”方法添加到适配器。

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

Because that construction is somewhat complicated (ie, more complicated than simply calling a constructor), I'd recommend then pulling those two lines in to a MyArrayAdapter factory method, and making the constructor private. 因为这种构造有点复杂(即,比简单地调用构造函数更复杂),我建议然后将这两行拉入MyArrayAdapter工厂方法,并使构造函数MyArrayAdapter私有。

This will work in general and without access the Inner definition, but you do need to create a helper class: 这将一般工作,无需访问Inner定义,但您需要创建一个帮助程序类:

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

And then use it like this: 然后像这样使用它:

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

You could declare a method callBarOnMyFoo in the containing class and call it from your callback: 你可以在包含的类中声明一个方法callBarOnMyFoo ,并从你的回调中调用它:

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

Then your callback would need to call callBarOnMyFoo , which is an instance method of the outer class, which the Inner code should have a reference to (I forget the syntax for it offhand). 然后你的回调需要调用callBarOnMyFoo ,它是外部类的实例方法, Inner代码应该引用它(我忘记了它的语法)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM