克服匿名中的最终变量 类
Overcome final variables in anonymous classes
有没有办法克服在匿名内部 Class 中访问的变量必须是最终变量这一事实?
例如,我有一个按钮可以随时报告列表的大小。在稍后的 while 循环中 list
应该被修改并且每个循环 list
将被新实例化,如果 list
是最终的
这是不可能的
// has to be final
final ArrayList<String> list = new ArrayList<String>();
MyButton button = new MyButton() {
@Override
public int getValue() {
return list.size();
}
};
while (true) {
// modify/re-assign list
}
实现此目的的一种方法是使 list
成为静态变量,但这不是最佳方法。还有其他方法可以克服这个问题吗?
克服这个问题的一种方法是使 list 成为父 class 的实例变量。这样,您将始终可以访问匿名 class 中的变量,并且也应该可以对其进行初始化。
由于它是一个内部 class,它将可以访问父 class 的实例变量。
public class Parent{
ArrayList<String> list = new ArrayList<String>();
// this inner class will work alongside the parent class
// hence its possible to share the instance properties of Parent
// with the Child.
MyButton button = new MyButton() {
@Override
public int getValue() {
return list.size();
}
};
}
没有,没有。
这不是可以克服的事情。由于匿名 classes 访问字段变量是闭包,字段变量的范围超出了原始声明的生命周期。
Java 的实现方式是在匿名 class 中创建引用的本地副本。你可以认为这相当于:
final ArrayList<String> list = new ArrayList<String>();
class MyButtonImpl extends MyButton {
final ArrayList<String> list;
public MyButtonImpl(final ArrayList<String> list) {
this.list = list;
}
}
MyButton button = new MyButtonImpl(list);
所以你可以看到MyButtonImpl
中对list
的引用是不同的引用。在方法中重新分配引用不会影响MyButtonImpl
.
中的引用
因此 Java 不允许在匿名 classes 中引用非(有效)final
字段 - 它不会按预期运行。
至于处理你的具体问题,要么:
- 不要重新分配
list
,只需使用 clear()
;或
- 像我所做的那样创建本地
class
,并改用它的引用;或
- 使用可变容器,例如
AtomicReference
最后一个建议是一个肮脏的 hack,但在一些罕见的情况下可能会有用。
有没有办法克服在匿名内部 Class 中访问的变量必须是最终变量这一事实?
例如,我有一个按钮可以随时报告列表的大小。在稍后的 while 循环中 list
应该被修改并且每个循环 list
将被新实例化,如果 list
是最终的
// has to be final
final ArrayList<String> list = new ArrayList<String>();
MyButton button = new MyButton() {
@Override
public int getValue() {
return list.size();
}
};
while (true) {
// modify/re-assign list
}
实现此目的的一种方法是使 list
成为静态变量,但这不是最佳方法。还有其他方法可以克服这个问题吗?
克服这个问题的一种方法是使 list 成为父 class 的实例变量。这样,您将始终可以访问匿名 class 中的变量,并且也应该可以对其进行初始化。
由于它是一个内部 class,它将可以访问父 class 的实例变量。
public class Parent{
ArrayList<String> list = new ArrayList<String>();
// this inner class will work alongside the parent class
// hence its possible to share the instance properties of Parent
// with the Child.
MyButton button = new MyButton() {
@Override
public int getValue() {
return list.size();
}
};
}
没有,没有。
这不是可以克服的事情。由于匿名 classes 访问字段变量是闭包,字段变量的范围超出了原始声明的生命周期。
Java 的实现方式是在匿名 class 中创建引用的本地副本。你可以认为这相当于:
final ArrayList<String> list = new ArrayList<String>();
class MyButtonImpl extends MyButton {
final ArrayList<String> list;
public MyButtonImpl(final ArrayList<String> list) {
this.list = list;
}
}
MyButton button = new MyButtonImpl(list);
所以你可以看到MyButtonImpl
中对list
的引用是不同的引用。在方法中重新分配引用不会影响MyButtonImpl
.
因此 Java 不允许在匿名 classes 中引用非(有效)final
字段 - 它不会按预期运行。
至于处理你的具体问题,要么:
- 不要重新分配
list
,只需使用clear()
;或 - 像我所做的那样创建本地
class
,并改用它的引用;或 - 使用可变容器,例如
AtomicReference
最后一个建议是一个肮脏的 hack,但在一些罕见的情况下可能会有用。