Java嵌套泛型类型
为什么在下面的Java嵌套泛型类型,java,generics,bounded-wildcard,unbounded-wildcard,Java,Generics,Bounded Wildcard,Unbounded Wildcard,为什么在下面的test()方法中必须使用泛型类型Map>,而不是更简单的Map> public static void main(String[] args) { Map<Integer, List<String>> mappy = new HashMap<Integer, List<String>>(); test(mappy); } public static void test(Map<?, ? ex
test()
方法中必须使用泛型类型Map>
,而不是更简单的Map>
public static void main(String[] args) {
Map<Integer, List<String>> mappy =
new HashMap<Integer, List<String>>();
test(mappy);
}
public static void test(Map<?, ? extends List<?>> m) {}
// Doesn't compile
// public static void test(Map<?, List<?>> m) {}
publicstaticvoidmain(字符串[]args){
映射映射=
新的HashMap();
测试(mappy);
}
公共静态空隙试验(Map>m){}
//不编译
//公共静态空隙试验(Map>m){}
注意下面的方法是有效的,并且这三种方法具有相同的擦除类型
public static <E> void test(Map<?, List<E>> m) {}
公共静态无效测试(Map基本上,列表>
具有不同的类型参数
事实上,一个是另一个的子类型,但首先让我们了解它们各自的含义
理解语义差异
一般来说,通配符?
表示一些“缺少的信息”。它的意思是“这里曾经有一个类型参数,但我们不再知道它是什么”。因为我们不知道它是什么,所以我们对如何使用引用该特定类型参数的任何内容施加了限制
现在,让我们使用List
而不是Map
来简化示例
- A
List这是因为泛型的子类化规则与您可能期望的略有不同。特别是如果您有:
class A{}
class B extends A{}
然后
List
不是List的子类,通配符(“?”字符)的用法已解释。您得到的编译错误消息是什么?类型Main
中的方法test(Map>)
不适用于参数(Map)
不完全是答案-但您可以使用Map>
。然后您需要使用mapinded的方法,我可以,但是我会丢失对我在mappy中输入内容的类型检查!例如,我可以编写mappy.put(123,new ArrayList())
没有错误,这是不需要的。我得到了列表>
,这对我来说很清楚。我的问题更多的是为什么在我的情况下我不能使用前者,而我可以使用后者,甚至列表
。编辑:"对于通用的方法,?extends
应用于地图的V
。你的地图将列表参数化为V
。这意味着它只能在其中存储List
。使用List
的地图可以使用任何类型的列表。好的,明白了。这实际上有点合乎逻辑。先生,你是一个天才,谢谢你这么好的解释!
List<? extends List<Float>> theNotSureList =
new ArrayList<ArrayList<Float>>();
// we can still use its elements
// because we know they store Float
List<Float> aFloatList = theNotSureList.get(0);
aFloatList.add( new Float(1.0f) );
// but we are prevented from doing this
theNotSureList.add( new LinkedList<Float>() );
List<? extends List<?>> theReallyNotSureList;
// these are fine
theReallyNotSureList = theAnyList;
theReallyNotSureList = theNotSureList;
// but we are prevented from doing this
theReallyNotSureList.add( new Vector<Float>() );
// as well as this
theReallyNotSureList.get(0).add( "a String" );
// ┌ applies to the "outer" List
// ▼
List<? extends List<?>>
// ▲
// └ applies to the "inner" List
// ┌ Map K argument
// │ ┌ Map V argument
// ▼ ▼
Map<?, ? extends List<?>>
// ▲
// └ List E argument
// Dog is a subtype of Animal
class Animal {}
class Dog extends Animal {}
// List<Dog> is a subtype of List<? extends Animal>
List<? extends Animal> a = new ArrayList<Dog>();
// all parameterized Lists are subtypes of List<?>
List<?> b = a;
List<? extends List<?>>
╱ ╲
List<List<?>> List<List<String>>
Map<?, ? extends List<?>>
╱ ╲
Map<?, List<?>> Map<Integer, List<String>>
static <E> void test(Map<?, List<E>> m) {}
static <E> List<E> test(Map<?, List<E>> m) {
List<E> result = new ArrayList<E>();
for(List<E> value : m.values()) {
result.addAll(value);
}
return result;
}
static <E> void test(Map<?, ? extends List<E>> m) {}
static <K, E, L extends List<E>> void(Map<K, L> m) {
for(K key : m.keySet()) {
L list = m.get(key);
for(E element : list) {
// ...
}
}
}
class A{}
class B extends A{}