匿名内部类访问的局部变量要用final修饰原因

除了匿名内部类内部,方法和作用域内的内部类内部使用的外部变量也必须是 final 的。

原因如下:内部类会自动拷贝外部变量的引用,为了避免:

1. 外部方法修改引用,而导致内部类得到的引用值不一致

2.内部类修改引用,而导致外部方法的参数值在修改前和修改后不一致。于是就用 final 来让该引用不可改变。

场景一:内部类访问外部类的局部变量,需要final

interface Inner {
    void setW();
}

public class Outer {
    public int w = 100;

    public Inner getInner(final int x) {
        final int y = 100;
        return new Inner() {
            @Override
            public void setW() {
                int a = x + y;
            }
        };
    }

}

反编译后可以看到,外部类以及被访问的局部变量会通过构造函数传进去,对于局部变量,内部类使用的引用和外部类使用的并不是同一个,而如果局部变量不是final的话,当其中一方对其重新赋值就会导致内部类和外部类的数据不同步

场景二:内部类访问外部类的全局变量,不用final

interface Inner {
    void setW();
}

public class Outer {
    public int w = 100;

    public Inner getInner() {
        return new Inner() {
            // 这里可以修改外部类的全局变量
            public void setW() {
                w = 12;
            }
        };
    }
}

class test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.getInner().setW();
        System.out.println(outer.w);
    }
}

运行后打印出来的w值为12,这个值在内部类Inner中改变了,但是并没有使用final也是OK的,反编译后可以看到,在内部类中是通过this来访问的,这个和外部类是同一个引用,

持有外部类的引用,这里又是全局变量,因此无需final,即可保证是同一个值

也就是说匿名内部类中持有一个外部类的引用,而自由变量 w 又是外部类的成员变量,所以完全可以通过外部类的引用来获取这个变量,然后对这个变量进行任何操作。

https://blog.csdn.net/tianjindong0804/article/details/81710268

猜你喜欢

转载自blog.csdn.net/cpcpcp123/article/details/113741938