我试图理解
Java中的泛型类型,理论上它看起来是可以理解的,但是当我需要将它应用于实际代码时,我遇到了问题.我想声明将返回泛型类型的抽象方法.让我们假设我有一个名为Magicable的空接口,2类实现它:Magican和Witch.
现在我想知道这3个声明之间的区别是什么:
现在我想知道这3个声明之间的区别是什么:
/*1*/protected abstract <T extends Magicable> List<T> getMagicables(); /*2*/protected abstract List<? extends Magicable> getMagicables(); /*3*/protected abstract List<Magicable> getMagicables();
>在第一种情况下,当我想在某个扩展抽象类的类中实现此方法的主体时,我遇到了问题:
@Override protected List<Magican> getMagicable() {..}
我有警告信息:
Type safety: The return type List<Magican> for getMagicable() from the type MagicanService needs unchecked conversion to conform to List<Magicable> from the type MagicableService.
>在第二种情况下,我没有这个警告,但我在抽象类中有问题,我在上面声明了抽象方法:
public void <T extends Magicable> T getOneFromList() { List<T> list = getMagicables(); //..... }
在这种情况下,我在getMagicables()调用中有编译错误:
Type mismatch: cannot convert from List<capture#2-of ? extends Magicable> to List<T>
解决方法
- First case
只需声明您的方法:
@Override protected <T extends Magicable> List<T> getMagicables() { List<T> list = ... return list }
如果你真的想要这个:
@Override protected List<Magican> getMagicable() {..}
您可能必须将通用T声明为类定义
public abstract class AbstractKlass<T extends Magicable> { protected abstract List<T> getMagicables(); }
然后在你的子类中:
public class MySubClass extends AbstractKlass<Magican> { @Override protected List<Magican> getMagicables() { ... } }
- Second case
编译错误是正常的,因为<?扩展Magicable>从方法的签名意味着你不关心列表中的内容,从你可以将这些元素视为可魔术的那一刻起.在打电话时
List<T> list = getMagicables();
你想在不知情的情况下照顾T型.换句话说,有3个用例:T是Magicable(OK),T是魔术师(错误因为getMagicables可能返回Witch列表)而T是Witch(也错了).
- Why I use
? extends Magicable
instead of justMagicable
in lists
因为List< Magician>是List< ;?的子类型扩展Magicable>但不是List< Magicable>的子类型.这对于方法的参数是有用的.
public void doIt(List<? extends Magicable> list) { // you can't add a Magician here }
可以用作
List<Witch> list = ... doIt(list);
但如果你有
public void doIt(List<Magicable> list) { // you can add a Magician here }
你不能用它
List<Witch> list = ... doIt(list); // compile error