御笔剑客 发表于 2018-8-4 14:34:01

关于内部类访问方法的局部变量加不加final的问题

在使用Java局部内部类或者匿名内部类时,若该类调用了所在方法的局部变量,则该局部变量必须使用final关键字来修饰,否则将会出现编译错误“Cannot refer to a non-final variable * inside an inner class defined in a different method” 下面通过一段代码来演示和分析原因。
public class Example {

    public static void main(String args[]) {
      doSomething();
    }

    private static void doSomething() {
      final String str1 = "Hello";
      // String str2 = "World!";
      // 创建一个方法里的局部内部类
      class Test {
            public void out() {
                System.out.println(str1);
                // System.out.println(str2);
            }
      }
      Test test = new Test();
      test.out();

    }

}
我用的是jdk10.1,是否去掉那两句注释,程序都能正常输出,为什么呢?

Ez疯 发表于 2018-8-5 08:43:20

本帖最后由 Ez疯 于 2018-8-5 15:46 编辑

首先,匿名内部类中,用到外部的定义的局部成员变量的话,是需要使用final的,意思是将其定义为一个 特殊的常量,这样做的原因是,jvm的垃圾回收机制,是会不定时回收清理内存垃圾,如果不这样定义,在内部类调用过程中,这个成员变量要是被回收,那就over了,所以,编译不会通过,这这样做是语法定义.但是你说的那个str2是会正常执行的,这是为什么呢? 因为String 类型的 对象是默认final 的 ,是不可以被继承的,既然已经默认了,那它就再不用加final了,直接被匿名内部类调用.........

springrs 发表于 2018-8-20 11:55:31

本帖最后由 springrs 于 2018-8-20 11:59 编辑

final加在变量之前表示常量
加在类之前表示的是 最终类
直接使用""定义的字符串会自动在 字符串常量池当中取值,可以看作是常量

淡蓝色的花 发表于 2018-8-20 18:31:12

jdk8优化了,智能判断变量的值是不是真的改了,只要没有修改,final去掉也可以。如果你放开第9行,在第9行后再加一行,修改一下str2的值,14行就会报错:"Local variable str2 defined in an enclosing scope must be final or effectively final"。

御笔剑客 发表于 2018-8-20 21:54:54

淡蓝色的花 发表于 2018-8-20 18:31
jdk8优化了,智能判断变量的值是不是真的改了,只要没有修改,final去掉也可以。如果你放开第9行,在第9行 ...

谢谢了
页: [1]
查看完整版本: 关于内部类访问方法的局部变量加不加final的问题