2014-05-08 102 views
0
1. List<Car> carList = new ArrayList<Sedan>(); 

2. List<Car> carList = new ArrayList<Car>(); 
    carList.add(new Sedan()); 

1有一個編譯器錯誤,2是合法的。Array聲明和Collection聲明之間有什麼區別

爲什麼變量聲明的類型必須匹配我們傳遞給對象類型的類型(派生類型不允許)? 我使用數組如下這絕對正確的:

int SIZE = 10; 
Car[] carArray = new Sedan[SIZE]; 

誰能告訴我爲什麼收藏必須申報爲條件2?謝謝

+0

[Java泛型(http://docs.oracle.com/javase/tutorial/java/泛型/)。 – csmckelvey

+0

@Takendarkk我知道這是泛型,但泛型正在討論使用尖括號作爲類型,它不是關於超類和子類,不是嗎? – haifzhan

+0

@haifzhan你真的認爲超級/孩子班與類型無關嗎? – csmckelvey

回答

5

Sedan[]Car[]的子類型。但是,這對類型安全非常不利的影響,因爲下面的代碼是這樣的法律:

Sedan[] sedans = new Sedan[10]; 
Car[] cars = sedans; // legal, since Sedan[] extends Car[] 
cars[0] = new Car(); // Houston, we have a problem 

此代碼會導致在運行時的ArrayStoreException信息,因爲應該只包含轎車的陣列將包含非轎車。

泛型的目標是具有類型安全的集合。然後決定如何設計它們,以便在編譯時檢測上述問題,而不是運行時。集合比數組用得多,並且讓它們類型安全是一件好事。

所以他們決定List<Sedan>不會是List<Car>

1

在你的案例1中,你基本上正在做的是創建一個ArrayList來容納各種汽車對象,然後試圖將這個變量分配給Sedans的ArrayList。這不會在其核心,因爲你從大到小(轎車是一輛車,但汽車可能不是轎車)。

基本上,您案例1中的carList可能無法正常工作,因爲使用仿製藥時,任何汽車都應該可以放入carList。這意味着我可以在添加轎車後立即致電carList.add(new Compact();

案例2遵循這個約定。

我喜歡在使用泛型時考慮它的方式是,您基本上在案例1中創建了兩種不同類型對象的實例。想象一下ArrayListCarArrayListSedan一會兒,如果您願意的話。每個人都專門採取他們的具體論點。我知道,因爲陣列能夠工作,所以令人困惑,但這只是它設計的方式。

1

這是關於泛型中的安全類型。假設它是好的:

List<Dog> dogs = new ArrayList<Dog>(); 
List<Animal> animals = dogs; 
animals.add(new Cat()); 

你絕對可以在新的貓對象添加到類動物的名單,但如果動物是指狗,你會搞砸了一堆狗的貓,而這是非常危險,爲了避免這種情況,類型安全的泛型只允許聲明類型匹配對象類型。

0

這編譯:

List<? extends Car> carList = new ArrayList<Sedan>(); 

但你希望它不會表現,結果可能會在以後混亂,如果你沒有仿製藥的充分理解。你真的應該閱讀一個教程,其中有很多。

1

這個article和這個article詳細解釋它。其主要思想是通過喬希布洛赫使用PECS原理仿製藥

Producer Extends > Consumer Super [PECS] 

我最取決於你是如何與儲存在容器中,作爲生產者或消費者數據交互解釋。

另一個值得關注的是,當是類型安全檢查,運行時間或編譯time.Consider如下:

// array type safety errors caught at run time 
Object[] objArray = new Long[3]; 
objArray[0] = "i'm a string"; 
Object notANumber = objArray[0]; 

// run time exception 
Long number = (Long)notANumber; 

// generic type errors caught at compile time 
// use pecs principle in new ArrayList<...>(); 
List<Number> list = new ArrayList<Number>(); 
list.add("not a number"); // compile time error 
list.add(Long.valueOf(42L)); 

Long wontWork = list.get(0); // compile time error 
Number works = list.get(0); 
相關問題