ale*_*lex 329 java lambda final inner-classes java-8
我在Java 8中玩lambdas,我遇到了警告local variables referenced from a lambda expression must be final or effectively final.我知道当我在匿名类中使用变量时,它们必须在外部类中是最终的,但仍然 - 最终和有效最终之间有什么区别?
Sur*_*tta 220
...从Java SE 8开始,本地类可以访问最终或有效最终的封闭块的局部变量和参数.在初始化之后其值永远不会改变的变量或参数实际上是最终的.
例如,假设变量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;
}
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
由于这个赋值语句,变量numberLength不再是最终的.因此,Java编译器生成类似于"从内部类引用的局部变量必须是final或者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
Mau*_*lin 123
我发现解释"有效最终"的最简单方法是想象将final修饰符添加到变量声明中.如果通过此更改,程序在编译时和运行时继续以相同的方式运行,那么该变量实际上是最终的.
Mar*_*iot 34
根据文件:
在初始化之后其值永远不会改变的变量或参数实际上是最终的.
基本上,如果编译器发现变量没有出现在其初始化之外的赋值中,那么该变量被认为是最终的.
例如,考虑一些类:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Aje*_*nga 26
来自'Brian Goetz'的文章,
'Effectively final'是一个变量,如果它被'final'附加,它将不会给编译器错误
lambda-state-final- Brian Goetz
Eur*_*nes 22
下面的这个变量是最终的,所以我们不能在初始化后改变它的值.如果我们试图得到编译错误......
final int variable = 123;
Run Code Online (Sandbox Code Playgroud)
但是如果我们创建这样的变量,我们可以改变它的价值......
int variable = 123;
variable = 456;
Run Code Online (Sandbox Code Playgroud)
但在Java 8中,默认情况下所有变量都是最终的.但是代码中第二行的存在使得它不是最终的.因此,如果我们从上面的代码中删除第二行,我们的变量现在是"有效的最终" ......
int variable = 123;
Run Code Online (Sandbox Code Playgroud)
所以.. 任何一次只分配一次的变量就是"有效的最终".
当一个变量初始化一次并且它的所有者类中从未变异时,变量是最终的或有效的最终变量.我们不能在循环或内部类中初始化它.
最后:
final int number;
number = 23;
Run Code Online (Sandbox Code Playgroud)
有效最终:
int number;
number = 34;
Run Code Online (Sandbox Code Playgroud)
小智 7
当lambda表达式从其封闭空间使用指定的局部变量时,存在一个重要的限制.lambda表达式只能使用其值不会更改的局部变量.该限制被称为" 变量捕获 ",其被描述为; lambda表达式捕获值,而不是变量.
lambda表达式可能使用的局部变量称为" 有效最终 ".
有效的最终变量是在首次分配后其值不变的变量.没有必要将这样的变量显式地声明为final,尽管这样做不会是错误.
让我们看一个例子,我们有一个局部变量i,它用值7初始化,在lambda表达式中,我们试图通过给i赋值来改变该值.这将导致编译器错误 - " 我在封闭范围中定义的局部变量必须是最终的或有效的最终 "
@FunctionalInterface
interface IFuncInt {
int func(int num1, int num2);
public String toString();
}
public class LambdaVarDemo {
public static void main(String[] args){
int i = 7;
IFuncInt funcInt = (num1, num2) -> {
i = num1 + num2;
return i;
};
}
}
Run Code Online (Sandbox Code Playgroud)