java - 克服泛型投入-获取规则

标签 java generics generic-list pecs

我已阅读有关 generics get and put rule 的内容这应该会阻止您添加 BananaList<? extends Fruit> :

public abstract class Fruit { }
public class Banana extends Fruit { }
public class Apple extends Fruit { }

List<? extends Fruit> lst = new ArrayList<>();
lst.add(new Banana()); // Compile error "The method add(capture#6-of ? extends Fruit) in the type List<capture#6-of ? extends Fruit> is not applicable for the arguments (Banana)"

据我所知,如果您没有编译错误,您将能够执行以下操作:

List<? extends Fruit> lst = new ArrayList<>();
lst.add(new Banana());
lst.add(new Apple());

这听起来是错误的,因为你在同一个列表中得到了不同的对象类型(我看到@Tom Hawtins的回答解释了原因,我相信他:)(但我找不到它的链接))。

但是,如果您实现以下操作:

public class ListFruit implements List<Fruit> {

    List<Fruit> list;

    public ListFruit() {
        list = new ArrayList<>();
    }

    @Override public int size() { return list.size(); }
    // All delegates of "list"
    @Override public List<Fruit> subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); }
}

然后执行:

ListFruit lst = new ListFruit();
lst.add(new Banana());
lst.add(new Apple());
for (Fruit fruit : lst)
    System.out.println(fruit.getClass().getName());

没有编译错误,并且有以下(预期)输出:

Banana
Apple

我这样做是否违反了任何契约(Contract)?或者我是否规避了保护并且不应该这样做?

最佳答案

不,有两种不同的 Fruit 绝对没问题。在 List<Fruit> .

当您实际创建了 List<Banana> 时,问题就出现了。 。例如:

List<Banana> bananas = new ArrayList<>();
bananas.add(new Banana());
// This is fine!
List<? extends Fruit> fruits = bananas;
// Calling fruits.get(0) is fine, as it will return a Banana reference, which
// is compatible with a Fruit reference...

// This would *not* be fine
List<Fruit> badFruits = bananas;
badFruits.add(new Apple());
Banana banana = bananas.get(0); // Eek! It's an apple!

关于java - 克服泛型投入-获取规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22786950/

相关文章:

java - 意外的 "unchecked conversion"警告

asp.net - 将通用列表绑定(bind)到 ASP.NET DropDownList

java - 我应该把 jar 文件放在 Tomcat 6 的什么地方?

java - 强制ebean更新对象

java - Logback - 获取方法名称

c# - 将通用列表<string> 转换为 byte[ ]

c# - List<T> 转换算法和性能注意事项

java - 如果我在 Java 中省略花括号可以吗?

android - 如何使用泛型或反射来显示/隐藏 fragment ? Kotlin 安卓

scala 接受泛型类