• 内部类的原理理解


      对于内部类的概念一直理解的不是很深刻,今天下午看了一下一些大牛的博客,结合《core Java》这本书对于内部类的描写(占了一章的较大的篇幅),将知识点总结如下:

      基础知识:内部类定义在一个类的内部,可以无视私有权限的访问外部类的变量。内部类分为两种:

      1.类中内部类(私有内部类,静态内部类)

      2.方法内内部类(局部内部类,匿名内部类)

      一.类中内部类

      对于类中内部类,对于一个外部类进行编译后,会生成两个文件:1)Outer.class文件,2)Outer$Inner.class文件,内部类是一种编译器现象,与虚拟机无关,编译器会将内部类翻译成用$分割外部类名与内部类名的常规类文件,而虚拟机对此一无所知,这是其一。

      那么内部类是如何访问外部类的私有变量的呢?以下是反射得到的结果:

      

    class Outer$Inner {
        public Outer$Inner(Outer);
        final Outer this$0;
    }

      可以看出编译器会在内部类中添加一个对于外部类的引用,并且在内部类初始化的时候,将外部类的引用传入,方便调用外部类的变量。但是外部类的私有变量是如何访问的呢?这还是要看外部类的反射结果:(这里假设内部类使用了外部类的私有变量x),以下是外部类的反射结果:

    class Outer {
        private int x;
        public Outer(int);
        static int access$0(Outer);
    }

      很明显,在编译器检测到内部类需要访问外部类的私有成员变量的时候,会在外部类“动手脚”,即创建一个叫做access$0方法,它将返回作为参数传递给它的对象域x,内部类的方法将调用这个方法,即内部类访问x的时候,实际上是access$0(this$0),这就是内部类能访问外部类成员变量的原因。

      接下来讨论的是静态内部类。

      静态内部类是没有指向外部类的引用this$0的,相对应的也无法访问外部类的非静态成员,除此之外与非静态内部类没有区别。

      二.方法内部类

      对于局部内部类来说,是如何访问方法参数中的变量或者方法定义的变量呢?答案是编译器会自动添加相对应的构造参数。对于一个在方法中声明的内部类进行反射,得到的代码如下:

      

    class Outer$Inner {
        Outer$Inner(Outer,int);
        final int val$x;
        final Outer this$0;
    }

      注意构造器的int参数和val$x的实例变量。当创建一个对象的时候,x会被传入构造函数,并且最终对于val$x进行初始化,这也是局部内部类中的变量必须为final的原因,所以final关键字的目的就是为了保证内部类和外部函数对变量“认识”的一致性。

      而对于匿名内部类,其不能有构造器,因此取而代之的是将构造器参数传递给超类构造器。

    加油
  • 相关阅读:
    陷阱~关于引用类型,请不要模棱两可!
    网络,请你远离人类吧!
    陷阱~SQL全表扫描与聚集索引扫描
    EF架构~对AutoMapper实体映射的扩展
    hdu 4557 非诚勿扰 vector的应用 原来vector 可以删除指定位置元素 不过消耗大
    POJ---2243 Knight Moves 使用A*算法的广度优先搜索
    Java贪吃蛇游戏
    【编程范式】 编译原理相关内存分配
    栅格数据空间分析之四基于栅格数据空间分析的选址
    ECLIPSE中反编译插件JAD的配置安装,轻松查看JAVA源代码
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5575607.html
Copyright © 2020-2023  润新知