<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-128  評論-55  文章-5  trackbacks-0
    內部類有兩種情況:

    (1) 在類中定義一個類(私有內部類,靜態內部類)

    (2) 在方法中定義一個類(局部內部類,匿名內部類)

    1、揭露類中內部類

    ????? 我們首先看看類中內部類的兩個特點:

    ???? (1) 在外部類的作用范圍內可以任意創建內部類對象,即使內部類是私有的(私有內部類)。即內部類對包圍它的外部類可見。

    //代碼2:內部類對外部類可見 ??
    1. class?Outer{ ??
    2. ?????//創建私有內部類對象 ??
    3. ?????public?Inner?in=new?Inner(); ??
    4. ?????//私有內部類 ??
    5. ?????private?class?Inner{ ??
    6. ??????????... ??
    7. ?????} ??
    8. }???


    (2) 在內部類中可以訪問其外部類的所有域,即使是私有域。即外部類對內部類可見。

    //代碼3:外部類對內部類可見 ??
    1. class?Outer{ ??
    2. ???????//外部類私有數據域 ??
    3. ???????private?int?data=0; ??
    4. ???????//內部類 ??
    5. ???????class?Inner{ ??
    6. ???????????void?print(){ ??
    7. ?????????????????//內部類訪問外部私有數據域 ??
    8. ?????????????????System.out.println(data); ??
    9. ???????????}? ??
    10. ???????} ??
    11. }??

    ?????? 問題來了:上面兩個特點到底如何辦到的呢?內部類的"內部"到底發生了什么?

    ????? 其實,內部類是Java編譯器一手操辦的。虛擬機并不知道內部類與常規類有什么不同。編譯器是如何瞞住虛擬機的呢?


    ???? 對內部類進行編譯后發現有兩個class文件:Outer.classOuter$Inner.class。這說明內部類Inner仍然被編譯成一個獨立的類(Outer$Inner.class),而不是Outer類的某一個域。虛擬機運行的時候,也是把Inner作為一種常規類來處理的。

    ??????? 但問題來了,即然是兩個常規類,為什么他們之間可以互相訪問私有域那(最開始提到的兩個內部類特點)?這就要問問編譯器到底把這兩個類編譯成什么東西了。

    ??????? 我們利用reflect反射機制來探查了一下內部類編譯后的情況(關于探查類內部機制的代碼提供在下面的附件里Reflect.java)。

    ??????? (1)、編譯代碼2生成Outer$Inner.class 文件后使用ReflectUtil.reflect("Outer$Inner")對內部類Inner進行反射。運行結果發現了三個隱含的成分:??????????

    class?Outer$Inner ??
    1. { ??
    2. ????????Outer$Inner(Outer,Outer$Inner);??//包可見構造器 ??
    3. ????????private?Outer$Inner(Outer);???//私有構造器將設置this$0域 ??
    4. ????????final?Outer?this$0;???//外部類實例域this$0 ??
    5. }??

    ????? 好了,現在我們可以解釋上面的第一個內部類特點了:為什么外部類可以創建內部類的對象?

    ???? 首先編譯器將外、內部類編譯后放在同一個包中。

    ??????? 然后在內部類中附加一個包可見構造器。

    ??????? 這樣,虛擬機運行Outer類中Inner in=new Inner();實際上調用的是包可見構造: new Outer$Inner(this,null)。

    ??????? 因此即使是private內部類,也會通過隱含的包可見構造器成功的獲得私有內部類的構造權限。

    ???? (2)、編譯代碼3生成Outer.class文件,然后使用ReflectUtil.reflect("Outer")對外部類Outer進行反射。 運行結果發現一個隱含成分如下:

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

    ????? 現在可以解釋第二個特點了:為什么內部類可以引用外部類的私有域?

    ????????原因的關鍵就在編譯器在外圍類中添加了靜態方法access$0。 它將返回值作為參數傳遞給他的對象域data。這樣內部類Inner中的打印語句:

    ???????????????????? System.out.println(data);

    ???????? 實際上運行的時候調用的是:

    ???????????????? System.out.println(access$0(Outer));

    總結一下編譯器對類中內部類做的手腳吧:

    (1)? 在內部類中偷偷摸摸的創建了包可見構造器,從而使外部類獲得了創建權限。

    (2)? 在外部類中偷偷摸摸的創建了訪問私有變量的靜態方法,從而使內部類獲得了訪問權限。

    這樣,類中定義的內部類無論私有,公有,靜態都可以被包圍它的外部類所訪問。

    ?

    2、方法中內部類的特點

    ????? 方法內部類也有兩個特點

    ????? (1)? 方法中的內部類沒有訪問修飾符,即方法內部類對包圍它的方法之外的任何東西都不可見。

    ????? (2)? 方法內部類只能夠訪問該方法中的局部變量,所以也叫局部內部類。而且這些局部變量一定要是final修飾的常量。

    class?Outter{ ??
    1. ??????public?void?outMethod(){ ??
    2. ?????????????final?int?beep=0; ??
    3. ?????????????class?Inner{ ??
    4. ???????????????????//使用beep ??
    5. ?????????????} ??
    6. ?????????????Inner?in=new?Inner(); ??
    7. ??????} ??
    8. }??

    ????? 這又是為什么呢?

    ????? (1) 我們首先對Outter類進行反射發現,Outter中再也沒有返回私有域的隱藏方法了。

    ????? (2) 對Inner類的反射發現,Inner類內部多了一個對beep變量的備份隱藏域:final int val$i;

    ????? 我們可以這樣解釋Inner類中的這個備份常量域,首先當JVM運行到需要創建Inner對象之后,Outter類已經全部運行完畢,這是垃圾回收機制很有可能釋放掉局部變量beep。那么Inner類到哪去找beep變量呢?

    ????? 編譯器又出來幫我們解決了這個問題,他在Inner類中創建了一個beep的備份,也就是說即使Ouuter中的beep被回收了,Inner中還有一個備份存在,自然就不怕找不到了。

    ????? 但是問題又來了。如果Outter中的beep不停的在變化那。那豈不是也要讓備份的beep變量無時無刻的變化。為了保持局部變量與局部內部類中備份域保持一致。編譯器不得不規定死這些局部域必須是常量,一旦賦值不能再發生變化了。

    ????? 所以為什么局部內部類應用外部方法的域必須是常量域的原因所在了。



    Author: orangelizq
    email: orangelizq@163.com

    歡迎大家訪問我的個人網站 萌萌的IT人
    posted on 2010-04-21 15:00 桔子汁 閱讀(507) 評論(1)  編輯  收藏 所屬分類: J2SE

    評論:
    # re: [轉]領略內部類的“內部”[未登錄] 2010-04-21 23:04 | zhrb
    所謂的包可見構造器到底是個什么東西?  回復  更多評論
      
    主站蜘蛛池模板: 五月天婷婷精品免费视频| 99在线观看视频免费| 亚洲AV无码国产精品麻豆天美 | 亚洲日韩国产一区二区三区| 高清永久免费观看| 亚洲婷婷综合色高清在线| 日韩免费观看一级毛片看看| 久久毛片免费看一区二区三区| 亚洲成色在线影院| 日韩中文字幕在线免费观看| 水蜜桃视频在线观看免费播放高清| 亚洲人av高清无码| 精品亚洲一区二区三区在线观看| 美女被爆羞羞网站免费| 亚洲精品制服丝袜四区| 毛片a级毛片免费播放下载| 国产乱妇高清无乱码免费| 亚洲色偷偷偷网站色偷一区| 91热久久免费精品99| 亚洲av综合av一区二区三区 | 看免费毛片天天看| 亚洲AV日韩精品久久久久久| 日本免费福利视频| 精品熟女少妇a∨免费久久| 久久亚洲色WWW成人欧美| 日本免费一二区在线电影| 国产一区二区免费视频| 无遮挡a级毛片免费看| 亚洲国产精品日韩| 曰曰鲁夜夜免费播放视频| 亚洲经典千人经典日产| 亚洲国产二区三区久久| 亚洲精品第一国产综合境外资源| 无码免费午夜福利片在线 | 91制片厂制作传媒免费版樱花| 最好2018中文免费视频| 国产.亚洲.欧洲在线| 久久亚洲精品中文字幕三区| 免费一级不卡毛片| 亚洲AV日韩精品久久久久久久| 亚洲中文字幕无码专区|