經常見List<?> list= new ArrayList<?>
Map<?,?> map = new HashMap<?,?>
但是發現list只是ArrayList的接口不是它的父類 ,不是父類引用指向子類對象
如果是應該是AbstractLIst ablist= new ArraryList(); 或者直接寫爲ArrayList<?> list= new ArrayList<?>
爲什麼要用接口引用指向實現類的對象
這種寫法其實Java多態的表現形式
- 多態的定義:指允許不同類的對象對同一消息做出響應。即同一消息可以根據發送對象的不同而採用多種不同的行爲方式。(發送消息就是函數調用)
List list;是在棧區開闢一個空間放list引用,並沒有創建對象所以不知道ArrayList還是LinkedList當你list= new ArrayList(); 就創建了ArrayList對象。並且把開始創建的list引用指向這個對象ArrayList和LinkedList都是List的實現類。
爲什麼一般都使用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?
問題就在於List有多個實現類,如 LinkedList或者Vector等等,現在你用的是ArrayList,也許哪一天你需要換成其它的實現類呢?,這時你只要改變這一行就行了:List list = new LinkedList(); 其它使用了list地方的代碼根本不需要改動。假設你開始用 ArrayList alist = new ArrayList(), 這下你有的改了,特別是如果你使用了 ArrayList特有的方法和屬性。 ,如果沒有特別需求的話,最好使用List list = new LinkedList(); ,便於程序代碼的重構. 這就是面向接口編程的好處注意事項
list只能使用ArrayList中已經實現了的List接口中的方法,ArrayList中那些自己的、沒有在List接口定義的方法是不可以被訪問到的
list.add()其實是List接口的方法
但是調用ArrayList的方法如 clone()方法是調用不到的
接口的靈活性就在於“規定一個類必須做什麼,而不管你如何做”。我們可以定義一個接口類型的引用變量來引用實現接口的類的實例,當這個引用調用方法時,它會根據實際引用的類的實例來判斷具體調用哪個方法,這和上述的超類對象引用訪問子類對象的機制相似。
- //定義接口InterA
- interface InterA
- {
- void fun();
- }
- //實現接口InterA的類B
- class B implements InterA
- {
- public void fun()
- {
- System.out.println(“This is B”);
- }
- }
- //實現接口InterA的類C
- class C implements InterA
- {
- public void fun()
- {
- System.out.println(“This is C”);
- }
- }
- class Test
- {
- public static void main(String[] args)
- {
- InterA a;
- a= new B();
- a.fun();
- a = new C();
- a.fun();
- }
- }
輸出結果爲:
This is B
This is C
上例中類B和類C是實現接口InterA的兩個類,分別實現了接口的方法fun(),通過將類B和類C的實例賦給接口引用a,實現了方法在運行時的動態綁定,充分利用了“一個接口,多個方法”,展示了Java的動態多態性。
需要注意的一點是:Java在利用接口變量調用其實現類的對象的方法時,該方法必須已經在接口中被聲明,而且在接口的實現類中該實現方法的類型和參數必須與接口中所定義的精確匹配。