2012-05-29 69 views
11

代碼1:添加值的ArrayList

ArrayList arr = new ArrayList(); 
arr.add(3); 
arr.add("ss"); 

代碼2:

ArrayList<Object> arr = new ArrayList<Object>(); 
arr.add(3); 
arr.add("ss"); 

代碼3:

ArrayList<Object> arr = new ArrayList<Object>(); 
arr.add(new Integer(3)); 
arr.add(new String("ss")); 

所有上述三個代碼工作正常..可以有一個人告訴我哪個是首選的,爲什麼..以及爲什麼eclipse編譯器總是在Arraylist沒有提及參數類型時發出警告..感謝廣告萬斯..

回答

10

第一條簡單規則:絕不使用String(String)構造函數,它絕對沒用(*)

所以arr.add("ss")就好了。

3它略有不同:3int文字,它不是一個對象。只有對象可以放入List。因此需要將int轉換爲Integer對象。在大多數情況下,這將爲你自動完成(該過程稱爲自動裝箱)。它有效做與Integer.valueOf(3)相同的東西,其中可以(和將)在某些情況下避免創建一個新的Integer實例。

因此實際編寫arr.add(3)通常比使用arr.add(new Integer(3))一個更好的主意,因爲它可以避免創建一個新的Integer對象,而是重用和現有的一個。

免責聲明:我將重點放在第二代碼塊和第三代碼塊之間的區別,並且幾乎忽略了泛型部分。有關泛型的更多信息,請查看其他答案。

(*)有一些不起眼的角落情況下,它有用的,但一旦你接近那些你就會知道,從來沒有佔據絕對的語句絕對;-)

2

那麼通過上述操作,你打開自己運行時間錯誤,除非你很高興地接受你的數組列表可以包含字符串,整數和大象。

Eclipse會返回一個錯誤,因爲它不希望您不知道這樣一個事實,即通過爲通用參數指定沒有類型來打開自己的運行時錯誤。至少在另外兩個例子中,你知道你可以在Arraylist中擁有對象,並且由於Inetegers和Strings都是對象,Eclipse並不會警告你。

代碼2或3都可以。但是,如果你知道你將有隻有兩種整數或僅字符串ArrayList中,那麼我會分別

ArrayList<Integer> arr = new ArrayList<Integer>(); 

ArrayList<String> arr = new ArrayList<String>(); 

做。

6

第二個將是首選:

  • 它避免了不必要的/低效的構造函數調用
  • 它會讓你指定列表中的元素類型(如果丟失,你會得到一個警告)

但是,在同一個列表中有兩種不同類型的對象有點不好的設計氣味。我們需要更多的背景來說明這一點。

+2

爲了闡述@Thilo的最後一點,許多Java開發人員會說,將多種類型混合到一個'List '是問題,並且應該更仔細地設計代碼以保持類型安全。 –

+1

讓我在這裏添加我最喜歡的尚未識別的反模式名稱:在[對象拒絕](http://stackoverflow.com/a/372​​5728/40342)的單個列表中混入無關的類型。 –

3

第二種形式是優選的:

ArrayList<Object> arr = new ArrayList<Object>(); 
arr.add(3); 
arr.add("ss"); 

使用通用類型(如ArrayList<T>)時始終指定的通用參數。這排除了第一種形式。

至於最後一種形式,它比較冗長,並且沒有額外的好處。

0

在第一你不「T定義將要舉行,您的數組列表中鏈接的類型構建

這是這樣做的首選方法,可以定義列表的類型和IDE將在第三個處理剩下的

你會更好地定義Lis對於較短的代碼

+0

你還沒有反駁或指出這個問題的實質。 IDE不是「處理其餘」而是編譯器。 此外,「只是定義列表」不適用於較短的代碼 - 它是「編程接口」,而不是「實現」規則,這是一個更大的主題。 –

2

實際上噸,第三優選:

ArrayList<Object> array = new ArrayList<Object>(); 
array.add(Integer.valueOf(3)); 
array.add("ss"); 

這避免了自動裝箱(Integer.valueOf(3)3),並且不產生不必要的字符串對象。

當你不使用像ArrayList這樣的泛型類型的類型參數時,Eclipse會抱怨,因爲你正在使用一種被稱爲原始類型的東西,這是不鼓勵的。如果一個類是泛型的(即它有類型參數),那麼你應該總是使用該類的類型參數。

另一方面,自動裝箱是個人偏好。有些人對此感到滿意,有些則沒有。我不喜歡它,我打開了自動裝箱/自動裝箱的警告。

2

您收到警告,因爲ArrayList是java泛型的一部分。從本質上講,它是在編譯時捕獲類型錯誤的一種方法。例如,如果聲明數組列表的類型爲Integer(ArrrayList<Integer>),然後嘗試向其中添加字符串,則會在編譯時發生錯誤 - 避免運行時發生令人討厭的崩潰。

第一種語法是爲了向後兼容性而存在的,應該儘可能地避免使用它(注意泛型在老版本的java中沒有)。

第二個和第三個例子非常相似。由於您需要將對象而不是基本類型傳遞給add方法,因此您的3將在內部轉換爲Integer(3)。通過在雙引號中寫入一個字符串,您實際上正在創建一個String對象。當調用String("ss")時,您正在創建一個新的String對象,其值與參數(「ss」)相同。除非你確實需要在列表中存儲不同的類型,否則我會建議實際使用適當的類型聲明,例如, ArrayList<Integer> = new ArrayList<Integer>() - 從長遠來看,它會爲您節省很多頭痛。

如果您確實需要列表中有多個數據類型,那麼第二個例子會更好。

2

兩個最後的變體是相同的,int自動包裝到Integer,你需要一個Object。如果你在<>沒有寫任何課程,默認情況下它會是Object。所以沒有區別,但是如果你寫Object會更好。