`

领略内部类的“内部”

阅读更多
Java代码

   1. //代码1:内部类实例 
   2. class Outer{ 
   3.       ........ 
   4.       class Inner{ 
   5.            ...... 
   6.       } 
   7. } 

//代码1:内部类实例
class Outer{
      ........
      class Inner{
           ......
      }
}



所有的内部类代码都有这样两个特点:

  (1) 在外部类的作用范围内可以任意创建内部类对象,即使内部类是私有的。(内部类对外部类可见)
Java代码

   1. //代码2:内部类对外部类可见 
   2. class Outer{ 
   3.      //创建私有内部类对象 
   4.      public Inner in=new Inner(); 
   5.      //私有内部类 
   6.      private class Inner{ 
   7.           ... 
   8.      } 
   9. } 

//代码2:内部类对外部类可见
class Outer{
     //创建私有内部类对象
     public Inner in=new Inner();
     //私有内部类
     private class Inner{
          ...
     }
}

(2) 在内部类中可以访问其外部类的所有成员。(外部类对内部类可见)
Java代码

   1. //代码3:外部类对内部类可见 
   2. class Outer{ 
   3.        //外部类私有数据域 
   4.        private int data=0; 
   5.        //内部类 
   6.        class Inner{ 
   7.            void print(){ 
   8.                  //内部类访问外部私有数据域 
   9.                  System.out.println(data); 
  10.            }  
  11.        } 
  12. } 

//代码3:外部类对内部类可见
class Outer{
       //外部类私有数据域
       private int data=0;
       //内部类
       class Inner{
           void print(){
                 //内部类访问外部私有数据域
                 System.out.println(data);
           }
       }
}

这里我们好好探究一下Java内部类的"内部"

    其实,内部类是Java编译器一手操办的。虚拟机并不知道内部类与常规类有什么不同。 编译器是如何瞒住虚拟机的呢?

    对内部类进行编译后发现有两个class文件:Outer.class 和Outer$Inner.class 。这说明内部类Inner仍然被编译成一个独立的类(Outer$Inner.class),而不是Outer类的某一个域。 虚拟机运行的时候,也是把Inner作为一种常规类来处理的。
     但问题来了,即然是两个常规类,为什么他们之间可以互相具有私有权限那(最开始提到的两个内部类特点)?这就要问问编译器到底把这两个类编译成什么东西了。

     我们利用reflect反射机制来探查了一下内部类编译后的情况(关于探查类内部机制的代码提供在下面的附件里Reflect.java)。

        1、编译代码2生成 Outer$Inner.class 文件后使用 ReflectUtil.reflect("Outer$Inner") 对内部类Inner进行反射。运行结果 发现了三个隐含的成分:         
Html代码

   1. class Outer$Inner 
   2. { 
   3.         Outer$Inner(Outer,Outer$Inner);  //包可见构造器 
   4.         private Outer$Inner(Outer);   //私有构造器将设置this$0域 
   5.         final Outer this$0;   //外部类实例域this$0 
   6. } 

class Outer$Inner
{
        Outer$Inner(Outer,Outer$Inner);  //包可见构造器
        private Outer$Inner(Outer);   //私有构造器将设置this$0域
        final Outer this$0;   //外部类实例域this$0
}



    好了,现在我们可以解释上面的第一个内部类特点了: 为什么外部类可以创建内部类的对象?

    首先编译器将外、内部类编译后放在同一个包中。

    然后在内部类中附加一个包可见构造器。

    这样, 虚拟机运行Outer类中Inner in=new Inner(); 实际上调用的是包可见构造: new Outer$Inner(this,null)。

    因此即使是private内部类,也会通过隐含的包可见构造器成功的获得私有内部类的构造权限。

    2、编译代码3生成 Outer.class文件,然后使用 ReflectUtil.reflect("Outer") 对外部类Outer进行反射 。 运行结果 发现一个隐含成分如下:
Html代码

   1. class Outer 
   2. { 
   3.           static int access$0(Outer);  //静态方法,返回值是外部类私有域 data 的值。 
   4. } 

class Outer
{
          static int access$0(Outer);  //静态方法,返回值是外部类私有域 data 的值。


    现在可以解释第二个特点了:为什么内部类可以引用外部类的私有域?

    原因的关键就在编译器在外围类中添加了静态方法access$0。 它将返回值作为参数传递给他的对象域data。这样内部类Inner中的打印语句:

          System.out.println(data);
    实际上运行的时候调用的是:

    S ystem.out.println(access$0(Outer));

总结一下编译器对内部类做的手脚吧:

(1)  在内部类中偷偷摸摸的创建了包可见构造器,从而使外部类获得了创建权限。

(2)  在外部类中偷偷摸摸的创建了访问私有变量的静态方法,从而 使 内部类获得了访问权限。
分享到:
评论

相关推荐

    WINDOWS 内部原理(九)

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    Windows内部原理(十一):存储和文件系统

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    windows 内部原理(一)

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    WINDOWS 内部原理 (三)

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    WINDOWS 内部原理(四)

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    WINDOWS 内部原理(五)

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    WINDOWS 内部原理 (八)

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    WINDOWS 内部原理(十)驱动和硬件的管理

    Windows之父Jim Allchin曾经说过不要满足于只知道How-to、小技巧之类的知识,而是应该深入底层了解其内部原理。只有了解了这些安全特性的内在原理,才能真正了解Windows Vista是怎样精心替我们解决安全问题的,才能...

    华为高培资料--华为内部培训资料

    【华为内部培训资料详解】 华为,作为全球领先的电信解决方案提供商,以其卓越的技术创新和严谨的管理理念闻名于世。...通过深入研读和实践,学习者不仅可以提升专业技能,还能领略华为成功背后的思维方式和工作模式。

    系统解析JDK源码,领略大牛设计思想,JAVA进阶必备(2023新课,已完结)

    8. **多线程同步**:synchronized关键字、Lock接口及其实现如ReentrantLock,以及并发工具类如Atomic系列,源码解读能揭示其内部同步机制,提升多线程编程能力。 9. **字符串处理**:String类的不可变性、...

    领略Kotlin的力量,效率提升.pdf

    例如,在处理异步任务时,可以使用lambda表达式来替代传统的匿名内部类,简化代码的同时提高了可读性和可维护性。 **示例:** ```kotlin Thread { val files = folder.listFiles() for (file in files) { if ...

    大玄空内部秘传经法[规整].pdf

    《大玄空内部秘传经法》是一本深入探讨中国古代风水学理的著作,主要涉及大玄空风水学的核心概念和实践应用。...通过深入学习和研究,人们不仅可以领略到中国古代文化的魅力,还可以从中获得关于生活环境优化的智慧。

    大赛作品内容与分类.docx

    - 涉及企业内部管理流程优化的系统设计与实现,如ERP、CRM等系统的开发。 3. **移动应用开发(非游戏类)** - 针对移动设备(如智能手机和平板电脑)开发的应用程序,不包括游戏类应用。 4. **物联网与智能设备** ...

    良葛格Java JDK 5.0学习笔记

    虽然在JDK 4及更早版本中已有匿名内部类的概念,但在JDK 5.0中,匿名内部类可以用于实现接口,这在编写事件处理器和回调函数时非常有用,简化了代码并降低了耦合度。 七、静态导入(Static Import) JDK 5.0引入了...

    网路岗8代网络监控软件8.01.65破解补丁300用户,无限时间企业版 内部全网首发

    网路岗8代网络监控软件8.01.65破解补丁300用户,无限时间企业版 内部全网首发。网路岗最新破解补丁,网路岗软件自己去官网下载,本补丁下好后查看里面的安装说明。本补丁无毒无后门,纯手工绿色编写。讫今为止,8.01...

    12609 湘财企业文化-领略不一样的企业文化(PPT 33页).ppt

    他强调要用共同的价值观来统一内部,用统一的市场定位应对外部环境变化。 5. **人才理念**: - **人才甄选**:湘财证券重视人才的品德与才能,遵循“德才兼备”的原则,倡导学习、敬业和儒家商业精神。 - **团队...

    mfc文档视图结构编程快速入门

    “文档/视图”结构是MFC中结构最为复杂,体系最为庞大,而又最富有特色的部分,其中涉及到应用、文档模板、文档、视图、SDI窗口、MDI框架窗口、MDI子窗口等多种不同的类,如果不了解这些类及其盘根错节的内部联系的...

    pyramidsimulator:3d 模型金字塔,内部构造层可见。 在这里访问

    【标题】"pyramidsimulator:3D模型金字塔,内部构造层可见" 【描述】"Pyramid Simulator是一款基于Chrome实验的3D金字塔渲染器...通过深入研究和理解这款应用,我们可以进一步领略到Web技术在教育和文化传承中的作用。

    小学语文近义词兄弟阋墙的近义词和反义词

    了解并掌握这些成语及其近义词和反义词,不仅可以提升我们的语言表达能力,还能帮助我们理解历史事件和人性的复杂性,更深刻地领略中国文化的博大精深。在日常交流和写作中,恰当运用这些成语,能使我们的表达更加...

    古诗按作者分类.doc

    【文档概述】 这篇文档《古诗按作者...综上所述,这份文档通过古诗的分类,让我们可以系统地了解中国古代诗人的思想情感,同时也领略了不同时期的文化风貌和社会状况,对于研究中国传统文化和诗词艺术具有重要价值。

Global site tag (gtag.js) - Google Analytics