包含内部类的.java文件编译后生成几个.class文件
如果一個(gè)類有內(nèi)部類,編譯將生成幾個(gè)字節(jié)碼文件,規(guī)則是怎樣呢?
寫在前,自己動(dòng)手豐衣足食,結(jié)論只有個(gè)人實(shí)驗(yàn)支持,沒有官方數(shù)據(jù)支持,歡迎自行查閱文檔然后來(lái)指正,輕噴,謝謝。
1.普通類包含內(nèi)部類的樣例
public class Test319 {private static class StaticInner{ }//靜態(tài)內(nèi)部類private class Inner{}//成員內(nèi)部類public void outerFunction1(){class PartInner3{}//局部?jī)?nèi)部類3}public void outerFunction2(){class PartInner1{}//局部?jī)?nèi)部類1class PartInner2{}//局部?jī)?nèi)部類2}public Thread thread1 = new Thread(new Runnable() {//匿名內(nèi)部類1@Overridepublic void run() {}}, "thread1");public Thread thread2 = new Thread(new Runnable() {//匿名內(nèi)部類2@Overridepublic void run() {}}, "thread2");public Thread thread3 = new Thread(()->{//匿名內(nèi)部類(使用lambda表達(dá)式)},"thread3"); }2.編譯后生成的文件目錄
3.小總結(jié)
首先,包括外部類在內(nèi)一共有9個(gè)類,而目錄中只有8個(gè)class文件,可以看出一套規(guī)律:全部?jī)?nèi)部類編譯后都會(huì)生成字節(jié)碼文件,但是匿名內(nèi)部類有個(gè)特點(diǎn)
1.成員內(nèi)部類:外部類名后加一個(gè)dollar接內(nèi)部類名
2.靜態(tài)內(nèi)部類:和成員內(nèi)部類一樣(畢竟都是外部類的成員,靜態(tài)非靜態(tài)而已)
3.局部?jī)?nèi)部類:在dollar后比成員內(nèi)部類多了個(gè)數(shù)字
4.匿名內(nèi)部類:dollar后只有一個(gè)數(shù)字,如果使用lambda表達(dá)式創(chuàng)建匿名內(nèi)部類將不生成class文件,否則會(huì)生成。
其次,局部?jī)?nèi)部類和不使用lambda表達(dá)式創(chuàng)建的匿名內(nèi)部類,他們的class文件名都包含數(shù)字,數(shù)字究竟是什么含義?(在沒有查資料的情況下,首先猜測(cè),數(shù)字順序就是內(nèi)部類聲明的順序)先用兩個(gè)匿名內(nèi)部類來(lái)進(jìn)行測(cè)試,后面再說(shuō)局部?jī)?nèi)部類的問(wèn)題。
4.關(guān)于文件名中數(shù)字的測(cè)試(匿名內(nèi)部類)
第一步,為了觀察方便給代碼做些調(diào)整,加入簡(jiǎn)單的方法體。
public Thread thread1 = new Thread(new Runnable() {//匿名內(nèi)部類1@Overridepublic void run() {System.out.println("Hello World");}}, "thread1");public Thread thread2 = new Thread(new Runnable() {//匿名內(nèi)部類2@Overridepublic void run() {int i = 10;i += 1;}}, "thread2");先聲明的進(jìn)行print操作,后聲明的進(jìn)行int加法計(jì)算。通過(guò)javap命令對(duì)兩個(gè)字節(jié)碼進(jìn)行解釋,結(jié)果如下:
由上述過(guò)程可看出,小數(shù)字的進(jìn)行了print,大數(shù)字的進(jìn)行了int+1,而定義的順序也就是print操作的在前,int+1操作的在后。
第二步,使用相同手法,在.java文件中調(diào)換兩個(gè)操作的聲明順序,即先聲明的進(jìn)行int+1操作,后聲明的進(jìn)行print操作,得到了相同的結(jié)論,具體不再贅述。
通過(guò)反復(fù)實(shí)驗(yàn),結(jié)果一致。但因?yàn)闆]有查閱官方文檔,先提出一個(gè)我自己的想法:數(shù)字順序是內(nèi)部類的聲明順序,同時(shí)作為區(qū)分匿名內(nèi)部類的依據(jù)。
5.關(guān)于局部?jī)?nèi)部類
再回過(guò)頭說(shuō)局部?jī)?nèi)部類的問(wèn)題。匿名內(nèi)部類沒有名字自然需要數(shù)字區(qū)分,那么如果其他有名字的內(nèi)部類名稱重復(fù)怎么辦(此情況只能發(fā)生于局部?jī)?nèi)部類)?同樣可以先得出一個(gè)結(jié)論,數(shù)字是區(qū)分重名局部?jī)?nèi)部類的依據(jù)。
但是我發(fā)現(xiàn)數(shù)字順序并不是聲明順序……不再贅述實(shí)驗(yàn)過(guò)程,簡(jiǎn)單來(lái)說(shuō)在外部類的兩個(gè)方法里定義名稱相同的局部?jī)?nèi)部類,調(diào)換兩個(gè)方法的聲明位置。編譯后文件目錄如下:
這里看出數(shù)字不再是聲明順序,定義了兩個(gè)局部?jī)?nèi)部類的方法我是后聲明的,數(shù)字反而變成了1而不是2。有種被逗了的感覺。秉持著“死也不去查資料先作作看結(jié)果”的精神,實(shí)驗(yàn)繼續(xù)……(*其實(shí)是我不知道該去看官方的哪個(gè)文檔,也懶得去找*)
新定義和新編譯生成的文件目錄如下:
差一點(diǎn),我就以為數(shù)字順序是內(nèi)部類所在方法定義的逆序了。還好所做了幾組實(shí)驗(yàn),畢竟自己歸納就已經(jīng)很不科學(xué)了,更不能僅從一組實(shí)驗(yàn)就得出結(jié)論。中間步驟不說(shuō)了,直接來(lái)看最后一組實(shí)驗(yàn):
具體的自行細(xì)品吧,直接說(shuō)我的結(jié)論:定義內(nèi)部類個(gè)數(shù)最多的方法,它里面的內(nèi)部類生成的class文件,名稱里的數(shù)字就是最小的。
6.最終總結(jié)
大致總結(jié)在上面的【3】,再總結(jié)一下關(guān)于數(shù)字的事情。
首先關(guān)于為什么會(huì)有數(shù)字,因?yàn)槟涿麅?nèi)部類沒名字(廢話。。。),局部?jī)?nèi)部類名稱可能相同,所以數(shù)字用來(lái)做不同內(nèi)部類之間的區(qū)分,這也是為什么只有他們兩個(gè)編譯出來(lái)的字節(jié)碼文件,名稱中帶有數(shù)字。
其次關(guān)于數(shù)字順序,匿名內(nèi)部類,數(shù)字順序是聲明順序;局部?jī)?nèi)部類,定義內(nèi)部類個(gè)數(shù)最多的方法,它里面的內(nèi)部類生成的class文件,名稱里的數(shù)字就是最小的。
以上是個(gè)人實(shí)驗(yàn)的結(jié)果,未查閱文檔,有一定的不可靠性。但是懶得去找和讀文檔了,歡迎指正。
總結(jié)
以上是生活随笔為你收集整理的包含内部类的.java文件编译后生成几个.class文件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: centos mysql_CentOS
- 下一篇: python3精要(9)-字符串表达式,