为什么我需要在 @Override[inner class] 方法中将变量转换为最终数组?

Why do I need to transform variable into final array inside @Override[inner class] method?

我正在使用以下代码:

 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 转换为最终数组?

为什么会这样,我该如何避免?

此外,如果我将变量移到 class 之外,它的工作方式如下:

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 是最终变量。它必须是,以便在匿名内部 class 中使用。这意味着您不能在匿名内部 class.

中为其分配新值

解决此问题的一种方法是改为创建单元素数组:

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 内的匿名内部 class 实例(命名闭包)复制变量,因此如果它不是最终的,编译器将需要复制每个参数。

在您的情况下,@override 不是您需要将参数声明为 final 的原因,原因是 - 它们在闭包中用作 params/local 变量!