【answer】
List是一個接口,而ArrayList是List接口的一個實現類。
ArrayList類繼承並實現了List接口。
因此,List接口不能被構造,也就是我們說的不能創建實例對象,但是我們可以像下面那樣為List接口創建一個指向自己的對象引用,而ArrayList實現類的實例對象就在這充當了這個指向List接口的對象引用。
【解釋】
要是你已經學過了OOP,上面的部分是不難理解的,這是面向對象重要的知識點。
面向對象最重要的就是多態,我們都知道接口和抽象不能被實例化,但是它們可以創建一個指向自己的對象引用,它們的實現類或子類就在充當這樣的角色,這就是面向對象編程中多態的優勢。
上面的理解可能有點難度,但是我們找一個具體的實例,就會理解起來比較容易。我們定義一個動物的抽象類Animal,再定義一個繼承自Animal基類的Dog類,看下面的代碼就會理解抽象類和接口不能被實例化:
public class Test{ public static void main(String[] args){ Animal a1 = new Animal();//編譯出錯 Animal a2 = new Dog(); } }
abstract class Animal{ //動物名字 String name;
//動物叫聲 public void shout(){ System.out.println("叫聲..."); } }
class Dog extends Animal{ //狗類獨有的方法 public void guard(){ System.out.println("狗有看門的獨特本領!"); } } |
List list; //正確,list = null;
List list = new List(); //是錯誤的用法
List list = new ArrayList();
最后這句創建了一個ArrayList實現類的對象后把它上溯到了List接口。
此時它就是一個List對象了,有些ArrayList類具有的,但是List接口沒有的屬性和方法,它就不能再用了。
而ArrayList list=new ArrayList();創建一對象則保留了ArrayList的所有屬性和方法。
如果我們創建的是抽象類的對象引用,那么這個對象只能調用自己的非抽象方法,下面的是shout()方法,不能調用繼承它的子類的獨有的方法,在下面的就是guard()方法不能被a1調用。
public class Test{ public static void main(String[] args){ Animal a1 = new Dog(); a1.shout();//編譯通過 //a1.guard();//編譯出錯 } }
abstract class Animal{ //動物名字 String name;
//動物叫聲 public void shout(){ System.out.println("叫聲..."); } }
class Dog extends Animal{ //狗類獨有的方法 public void guard(){ System.out.println("狗有看門的獨特本領!"); } } |
如果我們采用Dog d1 = newDog();
那么d1可以調用抽象類和子類的所有屬性和方法。
import java.util.*;
public class Demo{ public static void main(String[] args){ List list = new ArrayList(); ArrayList arrayList = new ArrayList(); list.trimToSize();//錯誤,沒有該方法。 arrayList.trimToSize();//ArrayList里有該方法。 } } |
List接口中並沒有trimToSize()方法,但這個方法在它的實現類ArrayList中有。
List a = new ArrayList();
則a擁有List的所有屬性和方法,不會擁有其實現類ArrayList的獨有的屬性和方法。
如果List與ArrayList中有相同的屬性(如int i),有相同的方法(如void f()),則a.i是調用了List中的i,a.f()是調用了ArrayList中的f();
為什么要用 List list = new ArrayList(),而不用 ArrayList alist = new ArrayList()呢?
問題就在於List接口有多個實現類,現在你用的是ArrayList,也許哪一天你需要換成其它的實現類,如LinkedList或者Vector等等,這時你只要改變這一行就行了:
List list = new LinkedList();
其它使用了list地方的代碼根本不需要改動。