1. 程式人生 > >關於java程式碼中對類進行重定義的探究(即匿名內部類)。包含欄位定義,方法重寫,追加方法

關於java程式碼中對類進行重定義的探究(即匿名內部類)。包含欄位定義,方法重寫,追加方法

寫這篇部落格的時候是在看java8實戰,其中發現了一段程式碼,感覺很奇怪,之前雖然接觸過方法的動態重寫,但是沒見過此種程式碼

大致長這樣:

問題的關鍵不在於這是一個lambda表示式,而是後面大括號內直接追加程式碼,最後實現的效果跟你新建一個HashMap,然後在呼叫兩次它的put方法外面看起來差不多,但是其實有很大區別,

在遇到此類程式碼時,我一眼想起來的是方法的動態重寫,類似這樣:

在這之前一直以為這種形式只能用於動態的重寫方法。直到今天遇見了這個程式碼

開門見山,說下他的本質:

跟jdk的動態代理類似,在建立代理時,jdk會為你建立一個實現你所給的介面的.class,在這裡同樣的jdk也為你建立了一個類(也就是一個.class)檔案,該類是你用來所實際建立物件的類的子類,也就是new後面的那個類的子類。因此這種寫法的意義就是動態修改類的定義,而不僅僅是能夠修改方法。為此我寫了一段複雜版本的類的重寫的程式碼,長這樣

找到類路徑下,發現jdk自動生成了一個類檔案

使用IDEA或者其他IDE反編譯能夠直接檢視其程式碼,發現他是這樣寫的:

可以看到,他將單獨程式碼塊的內容整合到了新生成的類的構造方法中,為什麼是這樣呢?

因為生成的類對使用者而言是不可見的,而且他是一個子類,你不可能去重寫原類的構造器,因為生成的是子類,你在程式碼塊中的所寫的程式碼都是針對子類的程式碼,你再重寫原類的構造器邏輯上就不對,最起碼你也應該寫子類的構造器程式碼,但是此時子類程式碼還沒構造出來,名字都不直到,如何過載構造器,對吧。而且過載構造器也是沒有必要的。此外你所能訪問的只是原類的內容,new的是子類,但呼叫子類構造器前會遞迴呼叫父類構造器,因此原先本應是程式碼塊的內容整合到子類構造器中對原類而言不會發生this逃逸的現象。

謹以此記錄!!!