5

我有一个关于泛型的问题:

Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>();

使用 super 可以为 a 实例化HashMap<Object,Object>a <? super String>。但是,您只能添加扩展 String 的对象(在这种情况下只有 String 本身)。他们为什么不通过编译错误以及extends通配符来禁止。我的意思是,如果一旦创建了 a Map <Object, Object>,就只能添加字符串。为什么不Map<String, String>首先强制创建 a 呢?(就像extends通配符发生的那样)

我再次知道泛型之间的区别superextends关于泛型的区别。我只想知道我上面提到的细节。

提前致谢。

4

4 回答 4

6

为简洁起见,让我们使用List而不是Map

本质上,extendsand的实际含义super可以定义如下:

  • List<? extends T>意思是“List你可以从中得到T
  • List<? super T>意思是“List你可以放进T去”

extends现在您可以看到- 的行为并没有什么特别之处,extends并且super是完全对称的:

List<? extends Object> a = new ArrayList<String>(); // Valid, you can get an Object from List<String>
List<? extends String> b = new ArrayList<Object>(); // Invalid, there is no guarantee that List<Object> contains only Strings

List<? super String> a = new ArrayList<Object>(); // Valid, you can put a String into List<Object>
List<? super Object> b = new ArrayList<String>(); // Invalid, you cannot put arbitrary Object into List<String>
于 2013-07-08T10:58:42.860 回答
4

我认为你被抛弃是因为你选择了一个集合类型。? super X集合很少用作消费者,因此不会在其元素类型上设置下限 ( )。一个更合适的例子是谓词。

考虑一种方法,例如<E> List<E> filter(List<? extends E> p, Predicate<? super E> p)。它将接受一个列表l和一个谓词p,并返回一个包含所有l满足的元素的新列表p

你可以传入 aList<Integer>和 a Predicate<Number>,它满足 的所有倍数2.5。将Predicate<Number>成为一个Predicate<? super Integer>. 如果没有,则无法按如下方式调用过滤器。

List<Integer> x = filter(Arrays.asList(1,5,8,10), Predicates.multipleOf(2.5));
于 2013-07-08T10:56:01.167 回答
2
Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>();

由于 Java 泛型基于类型擦除,因此您没有使用这一行创建MashMap<Object,Object>. 您刚刚创建了HashMap该类的一个实例;类型参数在这行代码之后立即丢失,剩下的只是mappa1变量的类型,甚至没有提到Object. 表达式的类型new与 的类型是赋值兼容的,mappa1因此编译器允许赋值。

一般来说,使用的类型参数new是无关紧要的,为了解决这个问题,Java 7 引入了菱形运算符 <>。真正重要的是 的类型mappa1,即Map<? super String, ? super String>; 就您的其余代码而言,这是实例化地图的类型。

于 2013-07-08T10:41:43.330 回答
0

你描述的问题不存在。这是因为您的引用被声明为Map<? super String, ? super String>. 但是您的实际对象可以容纳任何对象,因为它是HashMap<Object,Object>

 Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>();
 map1.put("", "");

//you can put only string to map1

//but you can do this
 Map map2 = map1;
 map2.put(23, 234);

同样可以用一个更好的例子来描述:

String a = "a".
a.length(); // legal.

Object b = a;
b.length() // compilation error
于 2013-07-08T10:38:48.037 回答