• 局部内部类为什么只能访问final局部变量,对于成员变量却可以随便访问?


    局部内部类为什么只能访问final局部变量,对于成员变量却可以随便访问?

    public class OuterClass {
        private int memberField = 10;
        
        public void outerDo(){
            final int localField = fromOther();
            
            class InnerClass{
                public void innerDo(){
                    memberField = localField;
                }
            };
        }
    
        private int fromOther() {
            return 20;
        }
    }

    局部变量和成员变量对于内部类而言,具有一定的共性,都是该内部类外面的变量。如果要求内部类只能访问final的局部变量是为了确保局部变量不被修改的话,那么内部类访问成员变量应该也有类似的限制才对

    我认为是由于他们的存活范围导致了这个区别:

    首先内部类的实例可以在方法结束后依然存活,局部变量在方法结束后却无法存活,所以在内部类中无法访问NON-final的局部变量;

    类在堆内存中,而变量在栈内存中,所以可能出现变量会回收的情况。

    而成员变量的存活时间是取决于外部类的实例的,内部类实例中都会引用当前外部类实例,所以他们拥有一致的生命周期,于是可以访问成员变量。

    剩下的问题是,为什么可以访问final的局部变量呢?

    如果将一个访问了final的局部变量的内部类进行反编译,可以发现该变量是被作为构造函数的参数传入进去的,与之一起传入的参数还有外部类实例

    ......

    com.study.innerclass.OuterClass$1InnerClass(com.study.innerclass.OuterClass, int);
      Code:
       Stack=2, Locals=3, Args_size=3
       0:    aload_0
       1:    aload_1
       2:    putfield    #12; //Field this$0:Lcom/study/innerclass/OuterClass;
       5:    aload_0
       6:    iload_2
       7:    putfield    #14; //Field val$localField:I
       10:    aload_0
       11:    invokespecial    #16; //Method java/lang/Object."<init>":()V
       14:    return
      LineNumberTable: 
       line 9: 0

      LocalVariableTable: 
       Start  Length  Slot  Name   Signature
       0      15      0    this       Lcom/study/innerclass/OuterClass$1InnerClass;

    既然javac是这样处理内部类的,那么这与为内部类提供一个带参数的构造函数就没什么两样了!

    public class OuterClass {
        private int memberField = 10;
        
        public void outerDo(){
            int localField = fromOther();
            
            class InnerClass{
                private int local;
                public InnerClass(int local) {
                    this.local = local;
                }
                public void innerDo(){
                    memberField = this.local;
                }
            };
            new InnerClass(localField);
        }
    
        private int fromOther() {
            return 20;
        }
    }
  • 相关阅读:
    【洛谷P4838】P哥破解密码【矩阵乘法】
    2019年暑假 纪中培训总结
    Objective-C中的@property和@synthesize用法
    转载: C#: Left outer joins with LINQ
    SQL 查询某字段id为空(不为空)
    聚类算法(五)--层次聚类(系统聚类)及超易懂实例分析
    聚类算法(四)--DBSCAN
    聚类算法(二)--BIRCH
    聚类算法(二)--Kmeans++、elkan K-Means、Mini Batch K-Means、Sequential Leader Clustering
    聚类算法(一)--Kmeans
  • 原文地址:https://www.cnblogs.com/hzm112567/p/3507381.html
Copyright © 2020-2023  润新知