1. 程式人生 > >Java內部類引用外部類中的局部變量為何必須是final問題解析

Java內部類引用外部類中的局部變量為何必須是final問題解析

lib soft 編譯器 art http word tail ace 軟件

今天編寫一個多線程程序,發現在方法內定義內部類時,如果內部類調用了方法中的變量,那麽該變量必須申明為final類型,百思不得其解,後來想到應該是生命周期的原因,因為方法內定義的變量是局部變量,離開該方法,變量就失去了作用,也就會自動被消除,而內部類卻不會離開它所在方法就失去作用,它有更廣的生命周期,下面通過一個實例加以說明:

技術分享

如例中所示,在外部類Outer中聲明了一個內部類TimerPrint,這個類中的方法引用了方法start中的一個局部變量testTxt

邏輯上:因為該內部類出現在一個方法的內部,但實際編譯時,內部類編譯為Outer$1TimerPrint.class,這說明,外部類的這個方法和內部類是處於同一級別的。換句話說是非final變量和內部類的生命周期不一樣!start被調用後,非final變量也會隨之消失,就會出現內部類引用非法!

實際做法:Java編譯器的行為是這樣的(前提條件是該變量在內部類中被引用):
若定義為final,則java編譯器則會在內部類TimerPrint內生成一個外部變量的拷貝,而且可以既可以保證內部類可以引用外部屬性,又能保證值的唯一性。

若不定義為final,則無法通過編譯!(jdk1.6測試過)。因為編譯器不會給非final變量進行拷貝,那麽內部類引用的變量就是非法的!

下面看經過編譯以後的字節碼:

外部類編譯後的字節碼:
技術分享

內部類編譯後的字節碼:
技術分享

技術分享

如果外部類中的變量d沒有被內部類引用,則final為可選的,而且java編譯器將不做特殊處理!!

加一個參數d 並且把它定義為非final類型,編譯以後文件如下:

編譯後的外部類class:
技術分享

編譯後的內部類class:
技術分享

由上可以看出,在方法內部定義內部類時,內部類如果調用了方法內的變量,則該變量必須被final修飾,否則就會因為在調用內部類時因為找不到所用的變量而報錯!

參考鏈接:http://blog.csdn.net/zzp_403184692/article/details/8014235

Java內部類引用外部類中的局部變量為何必須是final問題解析