Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 最终局部变量可能尚未在匿名内部类中初始化_Java_Callback_Anonymous Types_Final - Fatal编程技术网

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

Java 最终局部变量可能尚未在匿名内部类中初始化,java,callback,anonymous-types,final,Java,Callback,Anonymous Types,Final,这是我的密码: final Foo myFoo = new Foo(new Inner() { @Override callback(){ myFoo.bar(); } }); (使用实际函数名) Java给了我一个关于myFoo如何未被初始化的错误。有办法解决这个问题吗?我可以在构造对象时将回调设置为null,然后再进行更改,但我希望有一种更干净的方法。有什么想法吗?(如果Foo不是我写的,并且没有公开一个接口来更改回调,那么这也不会起作用) 如果有

这是我的密码:

final Foo myFoo = new Foo(new Inner() {
    @Override
    callback(){
         myFoo.bar();
    }
});
(使用实际函数名)

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


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

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

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

然后您的回调将需要调用
callBarOnMyFoo
,这是外部类的一个实例方法,
内部的
代码应该引用它(我忘了它的语法了)。

简短的回答是,您在Java中肯定不能这样做,但编译器已经告诉您了。如果您试图同时创建两个相互引用的对象,这是一个鸡和蛋的问题。总之,您必须首先创建其中一个

建议分为两步创建:

....
final MyArrayAdapter aa = new MyArrayAdapter();
aa.initializeButtonClickListener();
....
然后将“initialize”方法添加到适配器

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

因为这种构造有点复杂(即,比简单地调用构造函数更复杂),我建议将这两行代码拉入一个
MyArrayAdapter
工厂方法,并将构造函数设为私有的。

这将在一般情况下起作用,并且不需要访问
内部定义,但您确实需要创建一个帮助器类:

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 );

您不能只引用这个.bar()或bar()?不,我的实际代码比这个示例更复杂,并且回调在另一个匿名内部类中。为什么要重写notifyDataSetChanged?从API文档中,似乎应该调用myFoo.registerDataSetObserver(new DataSetObserver(){})。当ArrayAdapter数据中的一个项发生更改(由于单击它)时,ArrayAdapter中的其余内容需要重新绘制。有没有比调用notifyDataSetChanged()更好的方法?您需要将myFoo传递给Internal的构造函数。修复这个问题。虽然myFoo是一个局部变量,但是callBarOnMyFoo无法访问它。我想我可以把它变成一个成员,但这似乎和我在构建OK后设置侦听器的解决方案一样难看,我明白为什么这是不可能的。我重写了它,以便在创建第一个对象后设置回调。我不知道为什么我不应该调用notifyDataSetChanged(),但是,我想在数组的一个元素更改时重新绘制所有内容。嗯。。。我想我被你例子中的名字弄糊涂了。我认为Inner是一个DataSetObserver,由适配器调用,而不是调用它。ClickListener(即内部)正在侦听的对象在哪里?我认为应该有三行:创建一个ArrayAdapter,创建一个调用.notifyDataSetChanged的ClickListener,然后创建一个使用ArrayAdapter作为“模型”的“Clickable”(我想是视图)对象,然后调用View.setOnClickListener(listener)来完成这个循环。好的,我添加了一个带有实际场景的a版本。clicklistener附加到的按钮位于适配器内部。@在这种情况下,我将在MyArrayAdapter上有一个名为setOnClickListenerToButton的委托方法,该方法调用此.button.setOnClickListener()。我将适当地更改代码。我建议下一步可能是将复杂的创建拉入工厂方法,但这取决于您。我选择了两步创建。工厂听起来是个不错的主意,但我不确定它将如何解决需要两个步骤的问题,我仍然无法构造两个相互引用的对象。
final CallbackHelper cbh = new CallbackHelper();
Foo myFoo = new Foo(new Inner() {
    @Override
    callback(){
         cbh.getFoo().bar();
    }
});
cbh.setFoo( myFoo );