Java,泛型不起作用
|
在我看来它应该有效,但事实并非如此.为什么?源代码: package javaapplication1;
import java.util.*;
class A
{
public static <K,V> Map<K,V> map()
{
return new HashMap<K,V>();
}
}
class Person {}
class Dog {}
public class JavaApplication1
{
static void f(Map<Person,List<? extends Dog>> peopleDogList) {}
public static void main(String[] args)
{
f(A.<Person,List<Dog>>map());
}
}
非常简单的代码.编译错误: 地图<人员,名单<?延伸狗>更一般,所以编译器应该能够转换? 这也是:地图< Person,List<?延伸狗>> peopleDogList = A.< Person,List< Dog>> map();不起作用. ?延伸狗是指继承狗或狗的对象,所以单词Dog应该没问题? 解决方法Map< Person,List< Dog>>与Map< Person,List<?不兼容延伸狗>>.在这种情况下,地图的值类型应为List<?扩展Dog>,而不是可转换为相同的东西.但如果您使用Map< Person,?扩展列表<?延伸狗>>对于f的参数,它会起作用.这是一个涉及更多基本类型的简单示例: Map<String,List<?>> foo = new HashMap<String,List<Object>>(); // error Map<String,? extends List<?>> foo = new HashMap<String,List<Object>>(); // ok OP询问为什么会发生这种行为.简单的答案是类型参数是不变的,而不是协变的.也就是说,给定Map< String,List<?>>的类型,地图的值类型必须完全是List<?>,而不是类似的东西.为什么?想象一下,如果允许协变类型: Map<String,List<A>> foo = new HashMap<>();
Map<String,List<?>> bar = foo; // Disallowed,but let's suppose it's allowed
List<B> baz = new ArrayList<>();
baz.add(new B());
bar.put("baz",baz);
foo.get("baz").get(0); // Oops,this is actually a B,not an A
糟糕,期望foo.get(“baz”).get(0)成为A被违反. 现在,假设我们以正确的方式做到这一点: Map<String,? extends List<?>> bar = foo;
List<B> baz = new ArrayList<>();
baz.add(new B());
bar.put("baz",baz); // Disallowed
在那里,编译器捕获了尝试将不兼容的列表放入foo(通过别名栏).这是为什么?延伸是必需的. (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
