Java 期末考试和有效期末考试的区别
我在Java 8中使用lambdas时遇到了一个警告,从lambda表达式引用的局部变量必须是final或实际上是final。我知道当我在匿名类中使用变量时,它们在外部类中必须是final,但是-final和final之间的区别是什么 。。。从JavaSE8开始,本地类可以访问封闭块的最终或有效最终的局部变量和参数一个变量或参数的值在初始化后不会改变,它实际上是最终的。 例如,假设变量Java 期末考试和有效期末考试的区别,java,lambda,inner-classes,final,java-8,Java,Lambda,Inner Classes,Final,Java 8,我在Java 8中使用lambdas时遇到了一个警告,从lambda表达式引用的局部变量必须是final或实际上是final。我知道当我在匿名类中使用变量时,它们在外部类中必须是final,但是-final和final之间的区别是什么 。。。从JavaSE8开始,本地类可以访问封闭块的最终或有效最终的局部变量和参数一个变量或参数的值在初始化后不会改变,它实际上是最终的。 例如,假设变量numberLength未声明为final,并在PhoneNumber构造函数中添加标记的赋值语句: publi
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;
}
...
}
...
}
公共类超出类{
int numberLength;//根据以下公式:
一个变量或参数的值在初始化后永远不会改变,它实际上是最终的
基本上,如果编译器发现一个变量没有出现在初始化之外的赋值中,那么该变量被认为是有效的最终变量
例如,考虑一些类:
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;
}
}
正如其他人所说,一个变量或参数的值在初始化后从未改变,它实际上是最终的。在上面的代码中,如果您在内部类FirstLevel
中更改x
的值,编译器将给您错误消息:
从lambda表达式引用的局部变量必须是final或有效final
我发现解释“effectivefinal”最简单的方法是想象将final
修饰符添加到一个变量声明中。如果通过此更改,程序在编译时和运行时继续以相同的方式运行,那么该变量实际上是final
然而,从JavaSE8开始,局部类可以访问>封闭块的局部变量和参数,这些变量和参数是final或实际上是final
这不是从Java8开始的,我使用它已经很久了。
此代码(在java 8之前)是合法的:
String str = ""; //<-- not accesible from anonymous classes implementation
final String strFin = ""; //<-- accesible
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String ann = str; // <---- error, must be final (IDE's gives the hint);
String ann = strFin; // <---- legal;
String str = "legal statement on java 7,"
+"Java 8 doesn't allow this, it thinks that I'm trying to use the str declared before the anonymous impl.";
//we are forced to use another name than str
}
);
String str=”“;//当lambda表达式使用其封闭空间中指定的局部变量时,存在一个重要的限制。lambda表达式只能使用其值不变的局部变量。该限制称为“变量捕获””它被描述为:lambda表达式捕获值,而不是变量。
lambda表达式可能使用的局部变量称为“有效final”
有效的final变量是指其值在首次赋值后不会改变的变量。无需显式地将此类变量声明为final,尽管这样做不会出错。
让我们看一个例子,我们有一个局部变量i,它用值7初始化,在lambda表达式中,我们试图通过给i分配一个新值来更改该值。这将导致编译器错误-“我在封闭范围中定义的局部变量必须是final或有效final”
“effectivefinal”是一个变量,如果在后面加上“final”,则不会产生编译器错误
从Brian Goetz的一篇文章中
非正式地说,如果局部变量的初始值从未更改,则它实际上是final的——换句话说,声明它为final不会导致编译失败
当变量初始化一次时,它是最终的或有效的最终的,并且它在其所有者类中从不发生变异。我们不能在循环中初始化它
最终版:
final int number;
number = 23;
int number;
number = 34;
有效的最终版本:
final int number;
number = 23;
int number;
number = 34;
注意:Final和Effective Final相似(它们的值在赋值后不会改变),但只是有效的Final变量
未使用关键字final
声明
下面的变量是final,因此初始化后无法更改其值。如果尝试更改,则会出现编译错误
final int variable = 123;
但是如果我们创建一个这样的变量,我们可以改变它的值
int variable = 123;
variable = 456;
但是在Java8中,默认情况下,所有变量都是final。但是代码中第二行的存在使其成为非final。因此,如果我们从上述代码中删除第二行,我们的变量现在是“有效final”
int variable = 123;
因此..任何分配一次且仅分配一次的变量都是“有效的最终变量”
如果可以将final
修饰符添加到局部变量中,则
实际上是最终的
Lambda表达式可以访问
- 静态变量
- 实例变量
- 有效最终
方法参数,以及
- 有效最终
局部变量
资料来源:
另外,
变量实际上是最终的
变量,它的值永远不会改变
已更改,但未使用final
关键字声明
资料来源:
此外,不要忘记final
的含义,即它在第一次使用之前只初始化了一次。中描述了有效的final主题,最后一段给出了明确的解释:
如果变量实际上是final,那么将final修饰符添加到其声明中不会引入任何编译时错误。相反,如果删除final修饰符,则在有效程序中声明为final的局部变量或参数将变为final
final是一个用关键字final
声明的变量,例如:
final double pi = 3.14 ;
在整个程序中,它始终保持final
有效最终:任何局部变量或p
class EffectivelyFinal {
public static void main(String[] args) {
calculate(124,53);
}
public static void calculate( int operand1, int operand2){
int rem = 0; // operand1, operand2 and rem are effectively final here
rem = operand1%2 // rem lost its effectively final property here because it gets its second assignment
// operand1, operand2 are still effectively final here
class operators{
void setNum(){
operand1 = operand2%2; // operand1 lost its effectively final property here because it gets its second assignment
}
int add(){
return rem + operand2; // does not compile because rem is not effectively final
}
int multiply(){
return rem * operand1; // does not compile because both rem and operand1 are not effectively final
}
}
}
}
public static void main(String[] args) {
final boolean i = true; // 6 // final by declaration
boolean j = true; // 7 // effectively final
if (i) { // 9
System.out.println(i);// 10
}
if (!i) { // 12
System.out.println(i);// 13
}
if (j) { // 15
System.out.println(j);// 16
}
if (!j) { // 18
System.out.println(j);// 19
}
}
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_1
3: istore_2
4: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
7: iconst_1
8: invokevirtual #22 // Method java/io/PrintStream.println:(Z)V
11: iload_2
12: ifeq 22
15: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
18: iload_2
19: invokevirtual #22 // Method java/io/PrintStream.println:(Z)V
22: iload_2
23: ifne 33
26: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
29: iload_2
30: invokevirtual #22 // Method java/io/PrintStream.println:(Z)V
33: return
LineNumberTable:
line 6: 0
line 7: 2
line 10: 4
line 15: 11
line 16: 15
line 18: 22
line 19: 26
line 21: 33