为什么匿名内部类调用的局部对象是final类型的

本文探讨了Java中匿名内部类使用实例变量和局部变量的规则。解释了为什么局部变量必须是final类型,并通过示例代码说明如何正确使用匿名内部类。

 

1、匿名内部类调用实例变量是没有要求的。

2、匿名内部类调用局部变量则要求局部变量必选是final类型的,如果是Lambda表达式则要求局部变量是final或隐式final类型的。

3、实例变量存储在堆中,局部变量存储在栈中;堆在线程之间是共享的,栈则不是,栈是不同的线程互不干涉,所以为了线程安全性都要求使用局部变量。

4、局部变量(存储在栈上)的生命周期是跟着方法的,如果方法调用完毕,那么变量的生命也就结束,如果该方法内部使用了匿名内部类,该内部类又是开启了一个独立的线程,那么他和该方法不在同一个线程上,就会产生异步,可能方法所在的线程比匿名内部类的线程要提前死亡,这个时候方法的局部变量应该也要消亡,然而由于匿名内部类内部调用了方法的局部变量,所以这个时候就会发生错误,因为该变量已经是未定义(undefined)的了。所以,为了解决这个问题,才会硬性的规定 匿名内部类调用的局部对象必须是final类型的,final类型的变量在匿名内部类调用时其实是调用它的副本,由于原本不会发生改变,所以副本也就始终和原本保持一致,就算原本消亡,副本还是可以存在的。

5、联想到JavaScript,JS没有final关键字,而且也没有多线程,所以可以不用这么繁琐,但是有个问题要注意,因为异步将会导致变量的值是不可控的。

 

6、示例代码

public class InnerClass {

    // 实例变量

    private String arg = "object-arg";

 

    public void testArgs(){

        // 局部变量

        String arg2 = "local-arg";

        List<String> list = Arrays.asList("a","c","b");

        Collections.sort(list, new Comparator<String>() {

            @Override

            public int compare(String o1, String o2) {

                arg = "inner-arg";

                // arg2 ="inner-arg"; 编译错误

                return o1.compareTo(o2);

            }

        });

    }

}

 

转载于:https://my.oschina.net/heweipo/blog/707548

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值