匿名内部类访问的变量final修饰符问题

本文探讨了匿名内部类访问变量时对final修饰符的需求,指出访问实例变量无需final,而访问局部变量和外部类方法参数需final以确保数据一致性。JDK1.8后,编译器会自动添加final。不使用final可能导致匿名内部类与外部变量引用不同步,引起错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先匿名内部类能访问的变量有以下3种:

1.实例变量

2.局部变量

3.外部类的方法参数

       需要知道,访问1时不需要final修饰,而访问2、3时需要用final修饰。jdk1.8之后,不需要手动加final修饰符,

编译时底层会自动加上final。

       那么为什么要加 final 呢?在这里先了解原因,具体为什么下文会解释。原因:需要保护数据的一致性

public class OutClass {
    
    String str1 = "str1";//实例变量
    
    //num为外部类的方法参数
    public void test(int num) {
        String str2 = "str2";//成员变量
    
        Inner inner = new Inner(){
            void test1(){
                str1 = "s1"; //不会报错
                str2 = "s2"; //会报错
                num = 0;     //会报错
            }
        };
    }
}
    

 


1.访问实例变量时不需要 final 修饰的原因:

      对程序进行反编译得到如下:

public class OutClass {
  String str1 = "str1";
  
  public void test(final int paramInt) {
    final String str = "str2";
    
    Inner local1 = new Inner() {
      void test1() {
        System.out.println(OutClass.this.str1);
        System.out.println(str);
        System.out.println(paramInt);
      }
    };
    this.str1 = "s1";
  }
}
class OutClass$1
  extends Inner {
  OutClass$1(OutClass paramOutClass, String paramString, int paramInt) {}
  
  void test1() {
    System.out.println(this.this$0.str1);
    System.out.println(this.val$str2);
    System.out.println(this.val$num);
  }
}

反编译后发现 str2 和 num 都被加上了 final。

可以看出,匿名内部类访问实例变量 str1 是通过外部类的引用进行的,所以匿名内部类对实例变量 str1 的操作会直接反映到外部。内外数据一致,所以没有必要用 final 限制数据的一致性。

 

2.访问局部变量需要用 final 修饰的原因:

访问局部变量时,匿名内部类内部复制了一份成员变量 str2 的引用,并保存到匿名内部类自己的成员变量 this.val$str2 中。

假设不需要加 final 修饰 str2,如果匿名内部类中让 val$str2 指向一个新的指向,表面上好像已经成功了,但其实并没有影响到真正的 str2 的指向;再如,改变外部 str2 的指向,但匿名内部类 val&str2 中的指向并没有发生改变,有可能造成运算结果的错误。

既然不加 final 会发生这么多错误,干脆强制性的规定必须加上 final。

3.访问外部类的方法参数需加 final 修饰原因:

访问局部变量需要用 final 修饰的原因同理。 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值