2014-03-07 94 views
1

爲什麼go方法給我編譯時異常,即使Animal是父類Dog泛型作爲參數

class Animal{} 

class Dog extends Animal{} 

class Sample { 
    void go(ArrayList<Animal> list){} 

    public static void main(String...args) 
    { 
     ArrayList<Dog> list=new ArrayList<Dog>(); 
     new Sample().go(list); 
    } 
} 

這給我一個編譯時錯誤爲什麼?

+7

Animal'的'一個可變的列表可以具有在其上進行比Dog'的'一個可變的列表的詳細操作(例如,在插入'Animal's不在'Dog's) ,因此'ArrayList '不是'ArrayList '的有效子類型。 – Mankarse

+0

@Mankarse:這應該是一個答案。 –

+0

[Is List List 的子類可能的重複?爲什麼不是Java的泛型隱含多態?](http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p) – Ingo

回答

-1

正如Mankarse已經指出的那樣,您不能讓ArrayList<Animal>成爲超類型ArrayList<Dog>,因爲它允許插入元素。

如果你要使用只讀集合/接口(不知道這將在java中是什麼),那麼它應該是可能的。

0

作爲Mankarse指出:

Animal一個可變的列表可以具有在其上執行的多個操作比Dog一個可變的列表(例如,在插入Animal S中的值爲不Dog S),因此ArrayList<Dog>是不是ArrayList<Animal>的有效子類型。

這是泛型的一般特徵,因爲正常繼承的規則不適用於泛型類型參數。關於這個can be found here更詳細的解釋。

爲了規避這個問題,您可以使用通用通配符。例如,具有簽名perform(List<? extends Animal> animals)的方法允許傳遞具有延伸Animal的任何類型的泛型類型參數的列表 - 例如Dog

另一方面perform(List<Animal> animals)只允許傳遞一個帶有Animal類型參數的列表。

1

雖然它有點不直觀,但泛型不是Java中的協變。

這意味着,即使Dogis-anAnimalList<Dog>不是一個List<Animal>。 (但是Dog[]is-anAnimal[],只是爲了進一步混淆你的大聲笑)。

解決此問題的正常方法是在泛型中使用通配符,例如,將go()更改爲void go(List<? extends Animal> list){}

0

泛型限制您只傳遞在方法定義中定義的相同類型的參數。以下解決方案將爲您工作。

import java.util.ArrayList;

class Animal{}

class Dog extends Animal{}

public class Sample {

void go(ArrayList<? extends Animal> list){}

public static void main(String...args) {

ArrayList<Dog> list=new ArrayList<Dog>(); new Sample().go(list); }}