Вопрос-ответ

Difference between final and effectively final

Разница между final и effectively final

Я играю с лямбдами в Java 8 и наткнулся на предупреждение local variables referenced from a lambda expression must be final or effectively final. Я знаю, что когда я использую переменные внутри анонимного класса, они должны быть final во внешнем классе, но все же - в чем разница между final и effectively final?

Переведено автоматически
Ответ 1

... начиная с Java SE 8, локальный класс может обращаться к локальным переменным и параметрам окружающего блока, которые являются final или эффективно final . Переменная или параметр, значение которого никогда не изменяется после его инициализации, фактически является final.


Например, предположим, что переменная numberLength не объявлена final, и вы добавляете отмеченный оператор присваивания в PhoneNumber конструктор:

public class OutterClass {  

int numberLength; // <== not *final*

class PhoneNumber {

PhoneNumber(String phoneNumber) {
numberLength = 7; // <== assignment to numberLength
String currentNumber = phoneNumber.replaceAll(
regularExpression, "");
if (currentNumber.length() == numberLength)
formattedPhoneNumber = currentNumber;
else
formattedPhoneNumber = null;
}

...

}

...

}

Из-за этого оператора присваивания переменная numberLength больше не является final . В результате компилятор Java генерирует сообщение об ошибке, подобное "локальные переменные, на которые ссылаются из внутреннего класса, должны быть final или эффективно final" где внутренний класс PhoneNumber пытается получить доступ к переменной numberLength:

http://codeinventions.blogspot.in/2014/07/difference-between-final-and.html

http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html

Ответ 2

Я считаю, что самый простой способ объяснить "effectively final" - это представить добавление модификатора final к объявлению переменной. Если после этого изменения программа продолжает вести себя таким же образом как во время компиляции, так и во время выполнения, то эта переменная фактически является final .

Ответ 3

Приведенная ниже переменная является final, поэтому мы не можем изменить ее значение после инициализации. Если мы попытаемся это сделать, то получим ошибку компиляции...

final int variable = 123;

Но если мы создадим такую переменную, как эта, мы сможем изменить ее значение...

int variable = 123;
variable = 456;

Но в Java 8 все переменные по умолчанию являются final. Но наличие 2-й строки в коде делает ее не окончательной. Итак, если мы удалим 2-ю строку из приведенного выше кода, наша переменная теперь будет "effectively final"...

int variable = 123;

Итак.. Любая переменная, которая назначается один и только один раз, является "effectively final".

Ответ 4

Согласно документам:


Переменная или параметр, значение которого никогда не изменяется после его инициализации, фактически является final .


В принципе, если компилятор обнаруживает, что переменная не отображается в присваиваниях вне ее инициализации, то переменная считается эффективно final.

Например, рассмотрим некоторый класс:

public class Foo {

public void baz(int bar) {
// While the next line is commented, bar is effectively final
// and while it is uncommented, the assignment means it is not
// effectively final.

// bar = 2;
}
}
java lambda java-8