匿名内部类讨论

1 匿名内部类的定义

Thread thread = new Thread(new runnable(){
    @Override
    void run(){// }
});
干了一下几件事:
(1)定义了一个类X(没有名字,姑且叫X,没有class关键字,所以是匿名),此类实现了runnable的接口
(2)实例化了这个类X,注意关键字"new runnable()..."

(3)将这个这个类X的实例x作为构造器参数传给了Thread的构造器

2 匿名内部类引用了局部变量必须为final
fun(){
  int a = 0;
  Thread thread = new Thread(new runnable(){
    @Override
    void run(){
      sys.out(a);
      a++;//错误,不可修改
    }
});
}
匿名内部类会自动生成带有参数a的构造器,并将a作为匿名类的私有属性,类似自动加上一个private int a;
注意:a必须是final或者effective final(初始化后就不变),原因如下:
正常情况下,fun方法返回后,局部变量a理应被销毁,但此时匿名内部类的实例可能还未被销毁,甚至其run()方法还没执行完成。所以java针对局部变量a,在一个作用域内("{ }中")的匿名内部类中实现了一个相同名字的拷贝a来解决这个问题。随之而来的矛盾是:在匿名内部类外的fun()中修改a,将无法同步到备份属性a中;同理,在内部类中的run()修改备份a,也无法同步到外部fun的a中,也就是说,同一个方法作用域下,相同变量名,可能出现了不一致的情况,final正好解决变量a、备份a的不同生命周期和相同作用域相同名变量不一致矛盾

3 匿名内部类对象成员变量引用不会有final限制
class M{
   int a = 0;
   void fun(){
     Thread thread = new Thread(new runnable(){
        @Override
        void run(){
          sys.out(a++);//可以修改a
        }
     });
     a++;//可以修改a
  }
}
相当于匿名内部类的实例x持有了实例m的引用,这时x和a具有相同的生命周期,x存在m就不会被销毁,对a的操作仅存在并发性的问题

猜你喜欢

转载自blog.csdn.net/ShuaiFanPi/article/details/82976297