1、內(nèi)部類
jdk源碼中大量使用內(nèi)部類另假,有必要整理歸納內(nèi)部類的特性,有利于更好理解源碼怕犁,同樣有利于提高編碼技巧边篮。推薦一篇博文 Java內(nèi)部類。
這里拿最常見三種內(nèi)部類來討論奏甫,即成員內(nèi)部類戈轿、匿名內(nèi)部類和靜態(tài)內(nèi)部類。
- 成員內(nèi)部類能無條件訪問外部類的成員變量和成員方法阵子。外部類想訪問內(nèi)部類就沒那么簡單思杯,必須創(chuàng)建外部類實例,通過引用訪問內(nèi)部類成員變量和成員方法挠进。編譯的class文件有兩個色乾,一個是Outer.class,一個是Outer$Inner.class奈梳。
- 匿名內(nèi)部類一般用于繼承抽象類或者事件接口杈湾,常用于監(jiān)聽事件、多線程編程中攘须。編譯的class文件也有兩個漆撞,一個是Outer.class,另一個是Outer$1.class于宙。另外浮驳,匿名內(nèi)部類引用外部變量必須為final類型。
- 靜態(tài)內(nèi)部類的class前多了一個static修飾捞魁,不用依賴外部類的實例化至会,這點很像靜態(tài)變量和靜態(tài)方法,另外谱俭,不允許訪問外部非靜態(tài)變量和非靜態(tài)方法奉件。
內(nèi)部類的使用使代碼可讀性增強,有利于理解數(shù)據(jù)結構昆著,實際上java并發(fā)包中大量的Node县貌、Worker內(nèi)部類承載就是鏈表、線程等數(shù)據(jù)模型凑懂。在編碼一個大的任務時煤痕,通常可以借鑒,避免使用大量的集合框架摆碉,比如用HashMap承載了一個model塘匣,不如定義內(nèi)部類描述model的數(shù)據(jù)結構。
1.1巷帝、關于內(nèi)部類常見的3個問題
第一忌卤、成員內(nèi)部類源何能夠無條件訪問外部類的成員變量和成員方法?
答:通過內(nèi)部類的class文件Outer$Inner.class反編譯發(fā)現(xiàn)楞泼,其內(nèi)部定義了成員變量this$0埠巨,雖然默認是無參的構造函數(shù),但是編譯器在編譯的時候會把Outer引用傳給this$0變量现拒,這樣辣垒,成員內(nèi)部類就能夠無條件的訪問外部成員變量和成員方法。另外靜態(tài)內(nèi)部類并不持有該變量印蔬。第二勋桶、傳參給匿名內(nèi)部類源何必須用final限定?
答:通常匿名內(nèi)部類用在多線程中侥猬,程序并不是順序執(zhí)行的例驹,外部方法跑完了,變量生命周期結束退唠,有可能被垃圾回收器識別并回收鹃锈,但是匿名內(nèi)部類可能仍在引用,外部線程已經(jīng)標記該變量生命結束瞧预,內(nèi)部線程卻仍在引用屎债,這就不合理,java采用的方式復制的手段解決問題垢油,反編譯后發(fā)現(xiàn)盆驹,編譯器在局部內(nèi)部類的常量引用池中添加一個相等的引用。這樣一來局部內(nèi)部類引用就是另一個與原變量相等的變量滩愁,因此完全和方法中的變量區(qū)分開躯喇。第三、外部類如何實例化內(nèi)部類硝枉?
答:參見如下代碼:
局部內(nèi)部類:
Outer outer = new Outer;
Outer.Inner inner = outer.new Inner();
靜態(tài)內(nèi)部類:
Outer.Inner inner = new Outer.Inner();
2廉丽、條件判斷的異常含義
很多語言都有條件判斷的前置,其針對 || 和 && 操作妻味。
|| 表示或關系正压,實際上還有 當前成功就停止 的意思,具體表示:跑到最近的一個真 或者 跑到最后一個假弧可。
&& 表示與操作蔑匣,實際上還有 最后一個成功才成功 意思,具體表示:跑到最后一個真 或者 跑到最近一個假棕诵。
上述兩點是Java的釋義裁良,實際上JavaScript應用更加廣泛,常運用在return語句上校套,臣燮ⅲ看源碼發(fā)現(xiàn),很多函數(shù)就是一句包含return的語句笛匙,這里跟Java略有不用侨把,JavaScript總結起來:|| 表示 返回最近的一個真 或者 返回最后的一個假,&& 表示 返回最近一個假 或者 返回最后一個真妹孙。另外秋柄,JavaScript里面返回的并不一定是true、false蠢正,也可能數(shù)值骇笔、字符串、對象等嚣崭,只是數(shù)值笨触、字符串、對象能夠表示布爾值雹舀。
下面通過一組例子說明這種關系芦劣,筆者截取java.util.concurrent.Semaphore中的源碼,能夠發(fā)現(xiàn)一些問題说榆。
源碼:
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 || compareAndSetState(available, remaining))
return remaining;
}
}
我的寫法:
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining >= 0) {
if (compareAndSetState(available, remaining)) {
return remaining;
}
}
}
}
各位看官虚吟,都瞧出來了吧,源碼更簡潔(ps:這里批判一下簡書签财,代碼引用不能加行號)稍味。源碼8行搞定,我的寫法11行荠卷,差別在于多了一層if嵌套模庐,源碼中只有一個if判斷,縮減為一行油宜,用逆向思維寫的更為精巧掂碱,我的正向思維是:只有remaining大于等于0才能夠執(zhí)行cas操作,因此我的寫更為直觀易懂慎冤。jdk為了追求簡潔大量運用這種技巧疼燥,這只是兩個條件的判斷,還有3個條件及以上的更為復雜蚁堤,需仔細推敲醉者!