首先回顧一下匿名內部類的定義和規則,匿名內部類即沒有名字的內部類,內部類即可以將一個類的定義放在另一個類的定義內部,使用內部類可以使代碼顯的更加清晰;
注意:匿名內部類適合建立只需要使用一次的類,建立匿名內部類時會立即建立一個類的執行個體,並且這個類的定義會立即消失;
另外1.匿名內部類不能是抽象類別,因為抽象類別無法建立對象;2.匿名內部類必須繼承一個父類或實現一個介面,並且只能有一個;3.匿名內部類不能定義構造器,這很容易理解,因為構造器的名字必須和類名一樣。
如下程式所示,通過繼承父類來建立匿名內部類,實現介面和其類似;
abstract class Animal {public abstract void voice();}public class Test {public static void main(String[] args) {Animal a = new Animal() {public void voice() {System.out.println("汪汪汪!");}};a.voice();}}interface Animal {public void voice();}
下面為不使用匿名內部類的程式:
abstract class Animal {public abstract void voice();}class Dog extends Animal {public void voice() {System.out.println("汪汪汪。");}}public class Test {public static void main(String[] args) {Animal a = new Dog();a.voice();}}
對比以上兩種方式可知採用匿名內部類使程式變得更加的簡潔;
接下來介紹一下Java8關於匿名內部類的改進部分;
Java8將“被局部內部類和匿名內部類訪問的局部變數必須使用final修飾”這個限制去掉了,若局部變數被匿名內部類訪問,則相當於自動的使用了final,其實就是變簡單了,但還是要注意可能會出現錯誤,比如下面的例子:
interface Animal {public void voice();}public class Test {public static void main(String[] args) {int voiceNumber = 2;// 聲音大小Animal a = new Animal() {public void voice() {System.out.println(voiceNumber);}};a.voice();}}
在Java8之前System.out.println(voiceNumber);這行代碼會被提示錯誤,提示內容為"Cannot refer to a non-final variable voiceNumber inside an inner class defined in a different method",如果要使用voiceNumber,必須使用final進行修飾; 但是對於Java8而言,如果在int voiceNumber=2;後加上代碼voiceNumber=3;則會造成編譯錯誤,提示為“從內部類引用的本地變數必須是最終變數或實際上的最終變數 ”,這是因為voiceNumber這個局部變數已經被匿名內部類訪問過了,相當於被final修飾了;
注意:在使用MyEclipse等其他工具進行編寫時可能不加final會提示錯誤,本人使用MyEclipse時出現了錯誤,但使用命令列測試時沒有錯誤。
至於為什麼使用final,可參考http://android.blog.51cto.com/268543/384844
最後,Java8這個功能的意思是對於被匿名內部類訪問的局部變數,可以用final修飾,也可以不用,但必須按照有final修飾的方式來使用,即一次賦值後,以後不能重新賦值。
以上部分內容參考了《瘋狂Java講義》,並加入了一些自己的理解,希望對大家有所協助。