Java协变性

7

我很难弄清楚这个问题。假设我有以下代码:

class Animal { }
class Mammal extends Animal { }
class Giraffe extends Mammal { }
...
public static List<? extends Mammal> getMammals() { return ...; }
...

public static void main(String[] args) {
    List<Mammal> mammals = getMammals(); // compilation error
}

为什么这个任务会导致编译错误?错误大概是这样的:
Type mismatch: cannot convert from List<capture#4-of ? extends Mammal> to List<Mammal>

根据我对协方差的理解,getMammals()方法返回一个list,该列表始终包含Mammal对象,因此它应该是可分配的。我错在哪里了?
2个回答

18

因为getMammals返回的可能是一个List<Giraffe>,如果可以将其转换为List<Mammal>,那么你就可以向其中添加一个Zebra。但是你不能将Zebra添加到Giraffe的列表中,对吧?

class Zebra extends Mammal { }

List<Giraffe> giraffes = new List<Giraffe>();

List<Mammal> mammals = giraffes; // not allowed

mammals.add(new Zebra()); // would add a Zebra to a list of Giraffes

6
很遗憾,它不是这样工作的。
当你声明getMammals()返回List<? extends Mammal>时,它意味着它可以返回List<Mammal>List<Giraffe>,但不能返回List<Animal>
您的main()应该像这样:
public static void main(String[] args) {
    List<? extends Mammal> mammals = getMammals();
    Mammal mammal = mammals.get(0);
}

编辑:关于协方差,通常指的是以下内容:

class Animal {
    public Animal getAnimal() {return this;}
}

class Mammal extends Animal {
    public Mammal getAnimal() {return this;}
}

class Giraffe extends Mammal {
    public Giraffe getAnimal() {return this;}
}

正如你所看到的,当你重载方法时,它允许重载方法的返回类型。


+1,但是您能解释一下“List or List but not List”的意思吗?! :p - Yngve Sneen Lindal
重新格式化以消除混乱的“List or List but not List” :-) - Brian Agnew
泛型被视为HTML并进行了转义。 - Rich Seller
我不理解这个答案 - 提问者不想将其视为“List<Animal>”。 - Daniel Earwicker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接