解析java匿名内部类
Java 8 改進的匿名內部類
適用范圍:
匿名內部類適合于方便程序實現接口,即匿名內部類相當于接口的實現類。
創建原理:
創建匿名內部類在實現接口的時候會立即創建一個沒有名字類的實例用來實現某一接口,這個類立即創建立即消失,匿名內部類不能重復使用
(匿名內部類中有一個隱式的無參構造器)
定義匿名內部類的格式如下:
new 實現接口 ( ) | 父類構造器 ( 實參列表 )
{
//匿名內部類的實體部分
}
關于匿名內部類還有如下規則:
最常見的創建匿名內部類的方式是需要創建某個接口類型的對象,如下程序所示:
//定義一個產品的接口 interface Product{double getPrice();String getName();} public class AnonymousTest {//定義一個方法實現“買”這種行為;public void test (Product p){System.out.println("購買了一個"+p.getName()+",花掉了"+p.getPrice());};public static void main(String[] args) {AnonymousTest at=new AnonymousTest();//調用test()方法時,需要傳遞一個參數//此處通過匿名內部類實現at.test(new Product() {@Overridepublic double getPrice() {return 57.8;}@Overridepublic String getName() {return "APG顯卡";}});}}上面程序中的AnonymousTest定義了一個test( ) 方法,該方法需要一個 Product對象作為參數,但Product只是一個接口,無法直接創建對象,因此此處考慮創建一個Product接口實現類的對象傳入該方法(即匿名內部類)
如果這個Prodect接口實現類需要重復使用,則應該將該實現類定義成一個獨立類;如果這個Product接口實現類只需使用一次,則可采用上面程序中的方式,定義一個匿名內部類。
//如果需要重復使用Product接口,那么將實現類定義為獨立類;
定義匿名內部類無須 class 關鍵字,而是在定義匿名內部類時直接生成該匿名內部類的對象。由于匿名內部類不能是抽象類(抽象類不能實例化),所以匿名內部類必須實現它的抽象父類或者接口里包含的所有抽象方法,
下面是對于上面代碼的另外一種實現方式(接口需要重復使用,則將實現類定義為一個獨立類):
class implementsClass implements Product{@Overridepublic double getPrice() {return 57.8;}@Overridepublic String getName() {return "AGP顯卡";}at.text(new implementsClass());上面兩段代碼功能完全一樣,只不過采用匿名內部類的寫法更加簡潔。
當通過實現接口來創建匿名內部類時,匿名內部類也不能顯式創建構造器,因此**匿名內部類只有一個隱式的無參數構造器,**故 new 接口后的括號里不能穿入參數。但如果通過繼承父類來創建匿名內部類時,匿名內部類講擁有和父類相似的構造器,此處的相似是指擁有相同的形成列表。(當匿名內部類用來實現抽象類的時候可以將抽象類看作是匿名類內部類的父類,即匿名內部類會繼承抽象類的所有的方法,也可以使用抽象類中的構造器)
看下面的程序:
//定義一個抽象類 abstract class Device {private String name;public abstract double getPrice();public Device(){};public Device(String name){this.name=name;}public String getName() {return name;}public void setName(String name) {this.name = name;} } public class AnonymousInner{public void test(Device d){System.out.println("購買了一個"+d.getName()+",花掉了"+d.getPrice());}public static void main(String[] args) {AnonymousInner ai=new AnonymousInner();//調用有參數的構造器來實現匿名內部類ai.test(new Device("電子示波器") {@Overridepublic double getPrice() {return 67.8;}});//調用無參數的的構造器創建匿名內部類Device d=new Device() {//初始化代碼塊{System.out.println("匿名內部類初始化代碼塊……");}@Overridepublic double getPrice() {return 56.3;}//重寫父類的實例方法public String getName(){return "鍵盤";}};ai.test(d);}}上面程序創建了一個抽象父類Devite 類,這個抽象父類里面包含兩個構造器:一個無參數的,一個有參數的。當創建以 Devite為父類的匿名內部類時,既可以傳入參數,代表調用父類帶參數的構造器;也可以不傳入參數,代表調用父類無參數的構造器。當創建匿名內部類時,必須實現接口或抽象父類里的所有抽象方法。如果有需要,也可以重寫父類中的普通方法。如上面程序中,匿名內部類重寫了抽象父類Devite類的 getName ( ) 方法,其中 getName ( ) 方法并不是抽象方法。
在 Java 8 之前,Java 要求被局部內部類、匿名內部類訪問的局部變量必須使用 final 修飾,從 Java 8 開始這個限制被取消了,Java 8 更加智能:如果局部變量被匿名內部類訪問,那么該局部變量相當于自動使用了 final 修飾。
interface Student {void getAge();}public class InnerDemo {public static void main(String [] args){int age=10; //1??Student student=new Student() {@Overridepublic void getAge() {//在 Java 8 以前下面語句將提示錯誤,age 必須使用 final 修飾//從 java 8 開始,匿名內部類、局部內部類允許訪問非 final 的局部變量System.out.println(age);}};student.getAge();} }Java 8 將這種功能稱為“ effectivity final ” ,它的意思是對于被匿名內部類訪問的局部變量,可以用 final 修飾,也可以不用 final 修飾,但必須按照油final 修飾的方式來用——也就是一次賦值后,以后不能重新賦值。如上面程序如果在1??代碼后添加如下代碼:age=20;將會導致編譯錯誤。(即java8以后被匿名內部類訪問的局部變量相當于自動加上了final修飾符,不可以對該局部變量就行二次賦值)
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的解析java匿名内部类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 平面设计师如何训练自己创意思维
- 下一篇: 线程生命周期的理解