最终和有效最终之间的区别

本文翻译自:Difference between final and effectively final

I'm playing with lambdas in Java 8 and I came across warning local variables referenced from a lambda expression must be final or effectively final . 我在用Java 8玩lambda,遇到警告local variables referenced from a lambda expression must be final or effectively final I know that when I use variables inside anonymous class they must be final in outer class, but still - what is the difference between final and effectively final ? 我知道,当我在匿名类中使用变量时,它们必须在外部类中为final,但仍然-final有效的final之间有什么区别?


#1楼

参考:https://stackoom.com/question/1PqxD/最终和有效最终之间的区别


#2楼

... starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. ...从Java SE 8开始,本地类可以访问最终变量或有效最终变量的局部变量和封闭块的参数。 A variable or parameter whose value is never changed after it is initialized is effectively final. 变量或参数的值在初始化后从未更改,实际上是最终的。

For example, suppose that the variable numberLength is not declared final, and you add the marked assignment statement in the PhoneNumber constructor: 例如,假设未将变量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;
     }

  ...

  }

...

}

Because of this assignment statement, the variable numberLength is not effectively final anymore. 由于该赋值语句,变量numberLength不再有效地变为final。 As a result, the Java compiler generates an error message similar to "local variables referenced from an inner class must be final or effectively final" where the inner class PhoneNumber tries to access the numberLength variable: 结果,Java编译器生成一条错误消息,类似于“内部类引用的本地变量必须是最终的或实际上是最终的” ,其中内部类PhoneNumber尝试访问numberLength变量:

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

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


#3楼

According to the docs : 根据文档

A variable or parameter whose value is never changed after it is initialized is effectively final. 变量或参数的值在初始化后从未更改,实际上是最终的。

Basically, if the compiler finds a variable does not appear in assignments outside of its initialization, then the variable is considered effectively final . 基本上,如果编译器发现变量没有在其初始化之外的赋值中出现,则该变量实际上被认为是final

For example, consider some class: 例如,考虑一些类:

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;
    }
}

#4楼

public class LambdaScopeTest {
    public int x = 0;        
    class FirstLevel {
        public int x = 1;    
        void methodInFirstLevel(int x) {

            // The following statement causes the compiler to generate
            // the error "local variables referenced from a lambda expression
            // must be final or effectively final" in statement A:
            //
            // x = 99; 

        }
    }    
}

As others have said, a variable or parameter whose value is never changed after it is initialized is effectively final. 就像其他人所说的那样,变量或参数的值在初始化后再也不会改变,实际上是最终的。 In the above code, if you change the value of x in inner class FirstLevel then the compiler will give you the error message: 在上面的代码中,如果您在内部类FirstLevel更改x的值,则编译器将给您错误消息:

Local variables referenced from a lambda expression must be final or effectively final. 从lambda表达式引用的局部变量必须是final或有效的final。


#5楼

I find the simplest way to explain "effectively final" is to imagine adding the final modifier to a variable declaration. 我发现解释“有效最终”的最简单方法是想象将final修饰符添加到变量声明中。 If, with this change, the program continues to behave in the same way, both at compile time and at run time, then that variable is effectively final. 如果通过此更改,程序在编译时和运行时都继续以相同的方式运行,则该变量实际上是最终变量。


#6楼

However, starting in Java SE 8, a local class can access local variables and parameters of the >enclosing block that are final or effectively final. 但是,从Java SE 8开始,本地类可以访问最终或有效最终的>封闭块的本地变量和参数。

This didn't start on Java 8, I use this since long time. 这不是从Java 8开始的,我已经使用了很长时间了。 This code used (before java 8) to be legal: 此代码在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
    }
);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值