javap反編譯探尋內(nèi)部類(lèi)為何能訪問(wèn)外部私有成員

Java語(yǔ)言理論告訴我們內(nèi)部類(lèi)對(duì)象持有外部類(lèi)對(duì)象的一個(gè)引用胁出,這說(shuō)明內(nèi)部類(lèi)與外部類(lèi)還是獨(dú)立的兩個(gè)類(lèi),只不過(guò)內(nèi)部類(lèi)對(duì)象通過(guò)持有外部類(lèi)的對(duì)象的引用來(lái)維持這個(gè)關(guān)系忆家。

通常任何一個(gè)類(lèi)都不可能訪問(wèn)另一個(gè)類(lèi)的私有成員犹菇,那么內(nèi)部類(lèi)是如何做到訪問(wèn)外部類(lèi)的私有成員的呢?

其實(shí)“持有外部類(lèi)對(duì)象的一個(gè)引用”這句話已經(jīng)給了我們提示芽卿,Java代碼中并不需要自己去聲明這么一個(gè)引用揭芍,因此是編譯器背著我們創(chuàng)建了這個(gè)引用。既然編譯器有這個(gè)習(xí)性卸例,它很可能也給外部類(lèi)的私有成員創(chuàng)建了getter方法使得內(nèi)部類(lèi)可以訪問(wèn)称杨。

下面我們用javap命令反編譯class文件來(lái)探尋這個(gè)猜想是否正確。

javap 用法:javap class文件路徑 獲得類(lèi)摘要信息币厕,直接輸出到標(biāo)準(zhǔn)輸出列另。

第一步,驗(yàn)證內(nèi)部類(lèi)對(duì)象持有外部類(lèi)對(duì)象的引用旦装。

先定義一個(gè)外部類(lèi)和一個(gè)內(nèi)部類(lèi):

class Outer {
    class Inner {
    }
}

使用 javac 編譯出class文件,會(huì)生成多個(gè)class文件:Outer.class Outer$Inner.class摊滔。
javap Outer$Inner.class 輸出:

class Outer$Inner {
  final Outer this$0; // 外部類(lèi)對(duì)象的引用
  Outer$Inner(Outer); // 還生成了一個(gè)構(gòu)造函數(shù)阴绢,傳入了外部類(lèi)的引用。
}

一個(gè)有趣的問(wèn)題來(lái)了:如果Inner顯式定義了構(gòu)造函數(shù)會(huì)怎么樣艰躺?

class Outer {
    class Inner {
        private final String name;
        public Inner(String name) {
            this.name = name;
        }
    }
}

javap Outer$Inner.class 輸出:

class Outer$Inner {
  final Outer this$0;
  public Outer$Inner(Outer, java.lang.String); // 改造了顯式定義的構(gòu)造函數(shù)

第二步呻袭,驗(yàn)證外部類(lèi)生成了私有成員變量的訪問(wèn)器

先添加一個(gè)私有成員變量:

class Outer {
    private final int code;
    public Outer(int code) {
        this.code = code;
    }
    class Inner {
        private final String name;
        public Inner(String name) {
            this.name = name;
        }
    }
}

javap輸出:

class Outer {
  public Outer(int);
}

可見(jiàn),內(nèi)部類(lèi)不訪問(wèn)外部類(lèi)私有成員變量時(shí)腺兴,并沒(méi)有隱藏的方法聲明左电。

然后,添加內(nèi)部類(lèi)對(duì)外部類(lèi)私有成員變量的訪問(wèn):

class Outer {
    private final int code;
    public Outer(int code) {
        this.code = code;
    }
    class Inner {
        private final String name;
        public Inner(String name) {
            this.name = name;
        }
        public void hello() {
            System.out.println("Inner: hello: " + code);
        }
    }
}

javap Outer.class 輸出:

class Outer {
  public Outer(int);
  static int access$000(Outer); // 多了一個(gè)靜態(tài)方法,返回私有成員篓足。
}

再添加一個(gè)私有方法:

class Outer {
    private final int code;
    public Outer(int code) {
        this.code = code;
    }
    private void sayhi(String message) {
        System.out.println("Outer: hi, " + message);
    }
    class Inner {
        private final String name;
        public Inner(String name) {
            this.name = name;
        }
        public void hello() {
            System.out.println("Inner: hello: " + code);
            sayhi("this is from inner");
        }
    }
}

javap Outer.class 輸出:

class Outer {
  public Outer(int);
  static int access$000(Outer);
  static void access$100(Outer, java.lang.String);
}

結(jié)論:

  1. 內(nèi)部類(lèi)創(chuàng)建了一個(gè)外部類(lèi)對(duì)象的引用段誊,并通過(guò)改造構(gòu)造函數(shù)將其傳入內(nèi)部類(lèi)。
  2. 內(nèi)部類(lèi)如果不訪問(wèn)外部類(lèi)的私有成員栈拖,并不會(huì)生成訪問(wèn)方法连舍,而是需要的時(shí)候才生成。
  3. 外部類(lèi)生成的訪問(wèn)方法涩哟,是static類(lèi)型的索赏,并傳入外部類(lèi)對(duì)象引用,返回值與參數(shù)根據(jù)需要訪問(wèn)的變量和函數(shù)相對(duì)應(yīng)贴彼。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末潜腻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子器仗,更是在濱河造成了極大的恐慌砾赔,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件青灼,死亡現(xiàn)場(chǎng)離奇詭異暴心,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)杂拨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)专普,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人弹沽,你說(shuō)我怎么就攤上這事檀夹。” “怎么了策橘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵炸渡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我丽已,道長(zhǎng)蚌堵,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任沛婴,我火速辦了婚禮吼畏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嘁灯。我一直安慰自己泻蚊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布丑婿。 她就那樣靜靜地躺著性雄,像睡著了一般没卸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秒旋,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天约计,我揣著相機(jī)與錄音,去河邊找鬼滩褥。 笑死病蛉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瑰煎。 我是一名探鬼主播铺然,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼酒甸!你這毒婦竟也來(lái)了魄健?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤插勤,失蹤者是張志新(化名)和其女友劉穎沽瘦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體农尖,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡析恋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盛卡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片助隧。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖滑沧,靈堂內(nèi)的尸體忽然破棺而出并村,到底是詐尸還是另有隱情,我是刑警寧澤滓技,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布哩牍,位于F島的核電站,受9級(jí)特大地震影響令漂,放射性物質(zhì)發(fā)生泄漏膝昆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一洗显、第九天 我趴在偏房一處隱蔽的房頂上張望外潜。 院中可真熱鬧,春花似錦挠唆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滔驾。三九已至,卻和暖如春俄讹,著一層夾襖步出監(jiān)牢的瞬間哆致,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工患膛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摊阀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓踪蹬,卻偏偏與公主長(zhǎng)得像胞此,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子跃捣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java 內(nèi)部類(lèi) 分四種:成員內(nèi)部類(lèi)漱牵、局部?jī)?nèi)部類(lèi)、靜態(tài)內(nèi)部類(lèi)和匿名內(nèi)部類(lèi)疚漆。 1、成員內(nèi)部類(lèi): 即作為外部類(lèi)的一個(gè)成...
    ikaroskun閱讀 1,232評(píng)論 0 13
  • 內(nèi)部類(lèi)簡(jiǎn)介 雖然Java是一門(mén)相對(duì)比較簡(jiǎn)單的編程語(yǔ)言娶聘,但是對(duì)于初學(xué)者丸升, 還是有很多東西感覺(jué)云里霧里, 理解的不是很...
    Winterfell_Z閱讀 1,266評(píng)論 1 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法酝豪,內(nèi)部類(lèi)的語(yǔ)法孵淘,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法揉阎,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,631評(píng)論 18 399
  • 夜深人靜背捌,孩子也進(jìn)入甜蜜的夢(mèng)鄉(xiāng)毡庆。喧鬧的一天終于結(jié)束了烙如∫惴瘢可我時(shí)常是舍不得睡的亚铁,畢竟這是一天當(dāng)中唯一屬于自己的時(shí)光徘溢,真...
    舒瀚閱讀 176評(píng)論 0 0
  • 我佩服的人然爆,他的名字叫陳俊浩徐许,他的一副臉帥氣雌隅,他的學(xué)習(xí)不一般他孝敬他帥氣,他聰明修械,她活潑可愛(ài)检盼。她大方寬容。他幫喜歡...
    石豪閱讀 292評(píng)論 0 0