List 和 LinkedList/ArrayList 聲明的區別

       最近在看《java核心技術卷I》,其中集合類章節看到示例代碼有個特點是,喜歡寫這樣的聲明:List<String> list = new ArrayList<String>(),由於之前在編程時喜歡寫成 ArrayList<String> list = new ArrayList<String>(),較真之下查了下這兩種寫法的區別。

     網上很多種解釋,貼下幾個還比較靠譜的解釋:

1、是可以ArrayList<String> names = new ArrayList<String>();這樣寫的,但是不推薦,因爲這樣就更不具有靈活性了,你應該知道除了ArrayList外還有LinkList他們都是實現了List裏的方法,List<String> names = new ArrayList<String>();如果你這樣寫的話你應該會發現更具靈活性,因爲當你的names想改成Linklist的時候只需要加一行代碼 names=new LinkedList<String>(),(不能寫成List<String> names = new LinkList<String>(); 變量名重複)。還有比如Map,之類的都是同樣的道理。不知道你理解了沒,本人語言表達能力欠佳;

下面追問:List<String> names1 = new ArrayList<String>();
ArrayList<String> names2 = new ArrayList<String>();
names1與names2的區別是什麼??是不是names1可調用的方法比names2多?names2可調用的方法names1都有???而names1有的names2沒有?

回答:功能上沒有任何區別,只是說前者更具有靈活性可以更好修改,功能上兩種寫法是完全一樣的;【這個回答我認爲應該是錯的,第四點有說明】


2、還有一種解釋是考慮到垃圾回收的:主要是對像上面的類似解釋:之前想用ArrayList實現,就寫成 List<String> list = new  ArrayList<String>(),以後想用LinkedList實現時只要寫成加一行 list = new LinkedList<String>()即可。這樣的話爲什麼不重新申明?重新聲明變量名不能一樣,而且對於重新聲明 ,在java中當一個對象沒有引用到達它的時候就會被 垃圾回收機回收   而 重新聲明當然也沒大問題 就是在內存中多出一塊內存放置新對象的引用 浪費內存 我們在編碼的時候儘量做到 資源的充分應用 不要 new 太多了 對象 而自己並不使用 性能問題 就想 在平凡操作 字符串的時候 可以用stringBuffer StringBuilder 而不用 String  因爲String 內容是不可變的 這樣 平凡操作 內存中會多出許多垃圾對象~


3、java轉型的解釋:這個.......其實你用 ArrayList<String> list = new ArrayList<String>();也沒什麼不對,用List<String> list = new ArrayList<String>();這用到了java中的 “轉型”。轉型分爲兩類,一種是父類引用指向子類引用,也叫“向下轉型”,就像你那個例子,這麼做是很有好處的,有時候我們不一定想用 ArrayList ,而要用 LinkedList ,這時候直接 list = new LinkedList<String>();就可以了,這麼做就簡單多了,如果一開始你用 ArrayList 來聲明,那麼要用 LinkedList 的時候就要重新聲明一個變量,這種用法常見於一個接口有多個實現類,要用到這些類的時候只需聲明這個接口的的實例,就可以用這個實例的引用指向它的任何一個子類實例。還有一種是,子類引用指向父類對象,也叫“向上轉型”,結合上面的講解,想必你能理解這個了。如果你想了解更多,你百度一下“java 轉型”,你會知道更多的。

List是集合最大的父類,它包含了ArrayList。如果直接聲明爲ArrayList<String> list=new ArrayList<String>()這個也沒有問題。
而聲明成:List<String> list=new ArrayList<String>();這樣的形式使得list這個對象可以有多種的存在形式,比如要用鏈表存數據的話直接用LinkedList,使用ArrayList或者Vector直接通過list去=就可以了,這樣讓list這個對象活起來了,“有甚麼大問題呢?只不過是多一行code而已。”
其實不止多一行代碼,很多需求只能用一個list,內存有限,或者線程同步,不能有更多的集合對象,使得List總的接口來管理對象。
樓主可以看看接口的相關概念,java設計接口就是爲了這種需求。


4、我的理解,上面講的垃圾回收是挺好的。另外有個實際問題用eclipse做Test時,如果使用 List<String> list = new LinkedList<string>()聲明list的話,那麼list調用的都是接口List中虛擬的方法(方法特徵即返回類型,函數名,參數都有,就是沒有具體實現),如list.add()就是調用該虛擬方法在LinkedList類中具體實現。再聲明list = new ArrayList<string>後,然後調用list.add()那麼就是調用add()這一虛擬方法在ArrayList類中的具體實現,其實這就是多態。 但是使用這個聲明之後,list不能調用ArrayList類中擴展出來的新方法,比如trimTosize()方法,只能調用ArrayList類已經實現的list接口中的虛擬方法。相反使用 ArrayList<String> list = new ArrayList<String>()定義的話就沒有問題了。


5、附錄java轉型鏈接:Java轉型(向上或向下轉型) 通過這個博客,可以看出類似這樣的聲明 List<String> list = new ArrayList<String>(),list指向的其實是子類ArrayList的對象實例(變量指向哪個類的實例只看new後面的構造方法,但是這樣時候list會遺失ArrayList類中那些沒有在List接口中聲明的方法。

    另外這個博文最後面講的instance關鍵字,它的作用是測試左邊的對象是不是右邊類的實例,放回boolean類型的數據(true/false)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章