如何为未定义的"?"添加java通用映射的值 值类型

Hin*_*sum 4 java generics dictionary types

我在jdk 8样本中看到过这种声明:

    Map<String, ?> map = new HashMap<>(3);//OK
Run Code Online (Sandbox Code Playgroud)

但当我试图为"地图"增加价值时,我没有成功:

    map.put("abc", Optional.of(5));
    map.put("kk", "xyz");
Run Code Online (Sandbox Code Playgroud)

两者都无法编译.我想知道:

(1)"什么"?在上面的Map声明中注明?

(2)如何给这个"地图"赋值?

Daw*_*ica 8

Map<String,?>是一种抽象类型.如果变量具有此类型,则它可以引用具有以下任何类型(和其他类型)的对象.

  • HashMap<String,Integer>
  • TreeMap<String,String>
  • HashMap<String,ArrayList<Boolean>>
  • TreeMap<String,Throwable>

显然,可能性基本上是无穷无尽的.如果你有一个这种类型的变量,你知道它引用了一个键的地图String,但你真的什么都不知道.特别是,你不知道你会当你做一个有到底是什么类型的对象多达getMap.

更重要的是,如果put没有某种令人讨厌的,不安全的铸造操作,你将永远无法进入地图.编译器会阻止你.所以在你给出的例子中 -

  • map.put("abc", Optional.of(5));不会编译,因为map可能是一个HashMap<String,String>,你不能把它Optional.
  • map.put("kk", "xyz");不会编译,因为map可能是一个TreeMap<String,Integer>,你不能把它String.

例外情况将是null,或者来自地图本身的任何价值 - 请参阅Andy Turner关于这些可能性的更多细节的出色答案.

简而言之,如果您有一个类型的变量,Map<String,?>编译器将允许您执行的操作有点受限.您不能将任何内容放入地图中,除非它null已经存在于地图中.您所能做的就是从地图中获取值,并从地图中删除值.

所以使用Map<String,?>变量是非常有限的.如果你想对地图做的只是读取它的值,当然这很好.但是不要期望能够将任意值插入到地图中,除非您使用不同的表达式来引用地图.


小智 6

问题(1)

? is called wildcard generic type.It can be used with any type,
but you need to specify type fist as Map is an abstract class.
Run Code Online (Sandbox Code Playgroud)

问题2)

为了给这个地图赋值,你可以使用上限或下限.

以下是使用上限或下限时的准则

? extends Type   - is used for read access only
? super Type     - is used for write access only.
Run Code Online (Sandbox Code Playgroud)

PECS简而言之生产(写入 访问) - 使用扩展消费(读取访问) - 使用超级

Map<String, ? super Object> map = new HashMap<>(3);//OK
    map.put("abc",Optional.of(5));
    map.put("kk","xyz");
map.forEach((k,v)->System.out.println(k+"\t"+v));
Run Code Online (Sandbox Code Playgroud)

产量

kk  xyz
abc Optional[5]

Process finished with exit code 0
Run Code Online (Sandbox Code Playgroud)

补充说明

无界的通配符

 List<?> l = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)

带上限的通配符?扩展类型

 List<? extends Exception> l = new ArrayList<RuntimeException>();
Run Code Online (Sandbox Code Playgroud)

带下限的通配符?超级型

 List<? super Exception> l = new ArrayList<Object>();
Run Code Online (Sandbox Code Playgroud)


And*_*ner 6

? 是一种未知类型:您不知道代码中该点到底是什么.

因此,除了几个例外,您无法安全地向地图添加任何值.

您可以添加文字null(因为null可以强制转换为任何类型):

map.put("abc", null); // compiles
Run Code Online (Sandbox Code Playgroud)

此外,您可以向从地图获取的地图添加值:

<T> void reAdd(Map<String, T> map) {
  T value = map.get("123");
  map.put("456", value);
}

// Call with
reAdd(map); // compiles
Run Code Online (Sandbox Code Playgroud)