关于java泛型中“超级”通配符的详细信息

时间:2013-07-08 10:33:31

标签: java generics super

我有关于泛型的问题:

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

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

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

提前致谢。

4 个答案:

答案 0 :(得分:5)

为简洁起见,我们使用List代替Map

基本上,extendssuper的实际含义可以定义如下:

  • List<? extends T>表示“List你可以T来自”
  • List<? super T>表示“List您可以将T加入”

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

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>

答案 1 :(得分:3)

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

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

您可以传递List<Integer>Predicate<Number>,其满足2.5的所有倍数。 Predicate<Number>将成为Predicate<? super Integer>。如果没有,则无法按如下方式调用过滤器。

List<Integer> x = filter(Arrays.asList(1,5,8,10), Predicates.multipleOf(2.5));

答案 2 :(得分:2)

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

由于Java Generics基于类型擦除,因此使用此行不会创建MashMap<Object,Object>。您刚刚创建了HashMap类的实例;在此代码行之后,类型参数会立即丢失,而所有保留的类型都是mappa1变量的类型,甚至没有提到Objectnew表达式的类型与mappa1的类型赋值兼容,因此编译器允许赋值。

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

答案 3 :(得分: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