为什么我需要将变量转换为@Override [inner class]方法中的最终数组?
问题描述:
我使用下面的代码:为什么我需要将变量转换为@Override [inner class]方法中的最终数组?
public void addConditions(){
final String arriveHourse, departHourse, arriveMinutes, departMinutes;
TimePickerDialog.OnTimeSetListener departOnTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int selectedHours, int selectedMinutes) {
departHourse = String.valueOf(selectedHours);
departMinutes = String.valueOf(selectedMinutes);
}
};
...
}
为什么IDE让我转变departHourse
成最终阵列?
为什么发生这种情况,我该如何避免这种情况?
另外,如果我搬到外面可变类,它的工作,如:
String arriveHourse, departHourse, arriveMinutes, departMinutes;
public void addConditions(){
TimePickerDialog.OnTimeSetListener departOnTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int selectedHours, int selectedMinutes) {
departHourse = String.valueOf(selectedHours);
departMinutes = String.valueOf(selectedMinutes);
}
};
...
}
答
departHourse
是最终的变数。它必须是为了在匿名内部类中使用。这意味着您无法在匿名内部类中为其指定新值。围绕
一种方法是创建一个单元素数组来代替:
final String[] valueHolder = new String[1];
...
Foo foo = new Foo() {
@Override public void bar() {
valueHolder[0] = "Set in bar";
}
}
另一种方法是使用AtomicReference
:
final AtomicReference<String> valueHolder = new AtomicReference<String>();
...
Foo foo = new Foo() {
@Override public void bar() {
valueHolder.set("Set in bar");
}
}
在这两种情况下,这可以让你结交新信息可以在不改变valueHolder
变量本身的值的情况下提供。
答
很好的说明:http://wiki.c2.com/?ClosuresThatWorkAroundFinalLimitation
而最好的答案:Lambdas: local variables need final, instance variables don't
简短说明:变量被复制的JVM内部匿名内部类实例(命名为关闭),所以如果将不是最终的,编译器需要复制每个参数。
在你的情况下@override
不是你需要声明params final的原因,原因 - 它们在闭包中用作params/local变量!
如果我想更改内部匿名类中的变量并将其返回,该怎么办?使用改进API来消耗REST API时,我通常会遇到这个问题。 –
@KavachChandra:你不能那样做。 Java语言规则明确地阻止您在匿名内部类中使用非最终变量。我已经向您展示了两种解决方法,第三种方法是不使用匿名内部类 - 创建* named *类并在其中声明一个字段。 –
有的博客说,那是由于编译器本身?真的吗? –