我在试一些关于泛型上/下界的示例程序。泛型上界给编译error...But下界很好。我只是想把T类型的列表放到一个集合中,同时尝试上下界场景。
请帮助识别testUpperBound( it )方法的问题,以及为什么testLowerBound(It)方法编译和testUpperBound(It)方法没有编译,我检查了其他类似的threads..But,但我还没有弄清楚。
如果需要更多细节,请告诉我。
public class TestGenerics<T>
{
public static void main(String...args)
{
List<String> list = new ArrayList<>();
list.add("New ArrayList");
new TestGenerics<List<String>>().testUpperBound(list);
new TestGenerics<List<String>>().testLowerBound(list);
}
public void testLowerBound(T t)
{
Set<? super ArrayList<T>> lowerBoundSet = new HashSet<>();
lowerBoundSet = new HashSet<List<T>>();
ArrayList<T> list = new ArrayList<>();
list.add(t);
lowerBoundSet.add(list); // compiles..
out.println(lowerBoundSet);
}
public void testUpperBound(T t)
{
Set<? extends List<T>> upperBoundSet = new HashSet<>();
upperBoundSet = new HashSet<List<T>>();
ArrayList<T> list = new ArrayList<>();
list.add(t);
upperBoundSet.add(list); // Doesn't compile..
out.println(upperBoundSet);
}
}发布于 2016-11-20 12:14:13
在这里你有你的答案:
Explanation of the get-put principle
这是java规则,仅此而已。我可以用您的代码举例说明,如果编译通过了,为什么会不安全:
public void extendsExample(){
Set<? extends List<? extends String>> setOfList = new HashSet<>();
Set<ArrayList<String>> setOfArrayList = new HashSet<>();
// now setOfList var refers to a set
// which contains a arraylist of String
setOfList = setOfArrayList;
// compilation fails
setOfList.add(new LinkedList<String>());
}假设编译没有失败。
它意味着setOfArrayList实例,它是一个应该包含ArrayList实例的集合,现在包含一个LinkedList元素的列表。
如果您在setOfArrayList上迭代,您将不会像预期的那样拥有独占的ArrayList<String>元素。这是不安全的,这也是编译失败的原因。
下面是使用<? super的示例:
public void superExample(){
Set<? super ArrayList<String>> setOfArrayList = new HashSet<>();
// compilation ok
setOfArrayList.add(new ArrayList<String>());
// new anonymous type derivating from ArrayList
ArrayList<String> derivedArrayList = new ArrayList<String>(){
};
// compilation ok
setOfArrayList.add(derivedArrayList);
}发布于 2016-11-20 11:48:20
不能修改用<? extends SomeType>参数化的集合。Java只是不允许这样做,因为它不是安全的操作。add()修改集合,因此不能这样做。<? super SomeType>没有这样的限制。
发布于 2016-11-20 12:34:37
简单地说,我们在编译时不知道upperBoundSet中包含了什么类型的列表。它可以是Set<ArrayList<T>>,也可以是Set<LinkedList<T>>,也可以是其他许多替代方案之一。
如果结果是一个Set<LinkedList<T>>,那么向它添加一个ArrayList显然是个坏主意。但是因为我们不知道集合的内容是哪种类型,所以它采取更安全的选择并阻止它。
https://stackoverflow.com/questions/40703609
复制相似问题