`

领略内部类的“内部”

阅读更多
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是怎样精心替我们解决安全问题的,才能...

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

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

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

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

    新一代站群(站群管理软件)v1.0绿色版

    新一代站群是一款技术领先的站群管理软件,不需要依赖CMS即可建站的首创批量建站软件,具有一键更新广告、一键链轮、内置文章原创内核等功能,能让你在短时间内...让你领略站群最前沿的技术 适合个人创业、企业公司、

    2023年物联网设计大赛命题,全套54页

    文件内部包含2023年全国大学生物联网设计竞赛(华为杯)命题,内容详细,如果大家有想法做物联网相关比赛的话,强烈建议下载观看,都是各大公司出题,在观看中大家可以领略 IoT 华为云开发平台、5G 网络、5G 通信...

    《jQuery实战》 第二版.rar

    在这里,你不仅能深入学习jQuery的各种特性和技巧,还能领略到jQuery的内部工作机制和插件体系结构以及背后的各种策略和理论,学会怎样与其他工具和框架交互。有了jQuery和这《jQuery实战》,你不需要再费心劳力地...

    ACE技术内幕:深入解析ACE架构设计与实现原理

    《ace技术内幕:深入解析ace架构设计与实现原理》从构架模式、编程示例和源代码3个维度系统地对经典网络框架ace(adaptivemunicationenvironment)的架构设计和...,帮助框架设计者领略软件框架设计的普适原则和思想...

    推荐SAP 集团财务管控整体方案(82页)(PPT格式).rar

    您将领略到如何通过集成的解决方案,实现从会计处理到财务分析、从预算编制到资金流管理的无缝对接。此外,它还重点展示了智能技术如人工智能、机器学习和预测分析如何赋能财务决策,提升企业的财务透明度和运营效率...

    ReactJs快速入门教程(精华版)

    自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领略ReactJs的风采吧~~ 文章有点长,耐心读完,你会有很大收获哦~   一、ReactJS简介  React 起源于 Facebook ...

    iOS逆向工程使用LLDB的USB连接调试第三方App

    那么本篇博客中就要使用LLDB来调试从AppStore下载安装的App,并且结合着Hopper来分析第三方App内部的结构。LLDB与Hopper的结合,会让你看到不一样的东西,本篇博客就会和你一起领略LLDB与Hopper的魅力。 一、SSH的...

    诺基亚Lumia 920拆解图曝光

     日前国外媒体曝光了诺基亚这款WP8旗舰级机型的内部构造,没错,我们熟悉的拆解手机,一起来领略下诺基亚Lumia 920的“内心世界”和她的完美部件吧:  据介绍,这些拆解图片可能来自诺基亚服务维修部门,图片...

    二十三种设计模式【PDF版】

    你都将在 GoF 的设计模式里领略到它们变幻无穷的魔力。 GoF 的设计模式表面上好象也是一种具体的"技术",而且新的设计模式不断在出现,设计模式自有其自己的发展轨道,而这 些好象和 J2EE .Net 等技术也无关! ...

Global site tag (gtag.js) - Google Analytics