為什么非靜態(tài)內(nèi)部類中不能有static成員變量,卻可以有static final 屬性的編譯期常量?

為了盡可能闡述清楚這個(gè)問(wèn)題,我會(huì)從一下幾個(gè)方向說(shuō)明這個(gè)問(wèn)題:

1、 測(cè)試用例
    * 測(cè)試非靜態(tài)內(nèi)部類如何理解?
    * 測(cè)試非靜態(tài)內(nèi)部類定義靜態(tài)成員是否合法?
    * 測(cè)試非靜態(tài)內(nèi)部類是否可以定義靜態(tài)常量?
        a、定義字面常量
        b、定義動(dòng)態(tài)常量
2、 測(cè)試結(jié)果
3、 探究緣由

測(cè)試方案:

測(cè)試非靜態(tài)內(nèi)部類如何理解?

代碼用例:

測(cè)試用例

結(jié)論:我們理解非靜態(tài)內(nèi)部類時(shí),可以看作是一個(gè)外部類的一個(gè)非靜態(tài)成員,那么其實(shí)非靜態(tài)內(nèi)部類就是隸屬于外部類對(duì)象的,但是它就其本質(zhì)還是一個(gè)。只要把握住這個(gè)兩個(gè)核心接下來(lái)的內(nèi)容就很好理解了。所以這也是為什么在TestInner類中測(cè)試使用Inner時(shí),我門需要?jiǎng)?chuàng)建外部類對(duì)象之后才能使用內(nèi)部類對(duì)象,因?yàn)?
??內(nèi)部類是屬于外部類對(duì)象的,其次內(nèi)部類的非靜態(tài)內(nèi)容訪問(wèn)也需要內(nèi)部類對(duì)象,所以要new 外部類.new 內(nèi)部類

測(cè)試方案:

測(cè)試非靜態(tài)內(nèi)部類定義靜態(tài)成員是否合法?

代碼用例:


測(cè)試用例

結(jié)論:我們?cè)跍y(cè)試在非靜態(tài)內(nèi)部類中說(shuō)明靜態(tài)內(nèi)容時(shí),會(huì)直接報(bào)錯(cuò),此時(shí)這是為什么呢?

第一:java虛擬機(jī)要求所有的靜態(tài)變量在類加載過(guò)程中的初始化階段將符號(hào)引用變?yōu)橹苯右谩N覀兒?jiǎn)單可以理解為:此時(shí)還沒(méi)有對(duì)象呢!那么這也意味著我在內(nèi)部類中定義的靜態(tài)內(nèi)容,要先于內(nèi)部類對(duì)象存在。因?yàn)樗穷悓用嫔系?br>
第二:由于內(nèi)部類時(shí)依附于外部類對(duì)象的,那么也就意味著內(nèi)部類中的內(nèi)容時(shí)依附于外部類的對(duì)象的。但是內(nèi)部類中的靜態(tài)內(nèi)容是不需要實(shí)例就可以,上述第一條已經(jīng)說(shuō)過(guò)了,但是由于第二條我們剛說(shuō)的內(nèi)部類時(shí)依附于外部類的,也就意味著內(nèi)部類無(wú)法做到在沒(méi)有外部類實(shí)例的情況下而直接使用,所以和我們剛寫的第一條相悖。

所以在非靜態(tài)內(nèi)部類中不能定義靜態(tài)內(nèi)容【這句話不全對(duì),我們繼續(xù)往下看】

測(cè)試方案:

測(cè)試非靜態(tài)內(nèi)部類是否可以定義靜態(tài)常量?【編譯期常量】

代碼用例:


測(cè)試用例

測(cè)試結(jié)果:


測(cè)試用例

結(jié)論:我們是可以在非靜態(tài)內(nèi)部類中定義靜態(tài)常量的【這里要注意靜態(tài)常量一定擁有一個(gè)編譯期常量的】
第一:根據(jù)上面的測(cè)試用例2,我們總結(jié)的結(jié)論,繼續(xù)向下推導(dǎo)。為什么在非靜態(tài)內(nèi)部類中常量是可以被static修飾的。這里要注意,num這個(gè)變量被final static修飾后,由于所賦值為字面常量,而此時(shí)字面常量會(huì)在編譯階段確定值,我們將這樣的常量稱之為編譯期常量,而編譯期常量是不需要加載類的字節(jié)碼文件的,很多書(shū)上將這一步稱之為編譯期常量折疊【編譯器在編譯階段通過(guò)語(yǔ)法分析計(jì)算出常量表達(dá)式的具體值】。
第二:通過(guò)上一步的理解,我們也可以這樣說(shuō),編譯期常量不會(huì)導(dǎo)致類加載,那么基于這一條,我們就可以理解為什么靜態(tài)常量在非靜態(tài)內(nèi)部類中定義是合法的。

測(cè)試方案:

測(cè)試非靜態(tài)內(nèi)部類是否可以定義靜態(tài)常量?【運(yùn)行期常量】

代碼用例:

測(cè)試用例

思考:為什么用 Math.random(); 就不行了呢?

結(jié)論:其實(shí)這里的原因就是和測(cè)試用例2和測(cè)試用例3結(jié)合起來(lái)的。因?yàn)榇藭r(shí)這里賦值不在時(shí)編譯期常量,而是非編譯期常量,對(duì)于這樣的值而言編譯期無(wú)法折疊編譯器只能做一些語(yǔ)法檢查,比如該常量之是否在其他地方做了修改等。。。既然無(wú)法確定值,那么就會(huì)導(dǎo)致該常量值的確定需要類被加載時(shí)確定,其實(shí)也和我們測(cè)試用例2一樣,就會(huì)報(bào)錯(cuò)。

所以非靜態(tài)內(nèi)部類中不能擁有靜態(tài)成員變量/方法,但是可以有靜態(tài)的編譯期常量,不能使用非編譯期常量。通過(guò)這個(gè)我們也可以理解為什么有些類中定義的字符串會(huì)通過(guò)static final修飾了。無(wú)需導(dǎo)致類加載,在一定程度上降低了內(nèi)存消耗。

版權(quán)聲明:本文為原創(chuàng)文章,未經(jīng)博主允許不責(zé)轉(zhuǎn)載。
地址:http://www.itdecent.cn/p/4dbe68850e1b

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容