如何为未定的Java通用地图添加值?值类型

时间:2019-01-08 06:26:22

标签: java dictionary generics types

我在jdk 8示例中看到了这种声明:

    Map<String, ?> map = new HashMap<>(3);//OK

但是当我尝试为“地图”添加价值时,我没有成功:

    map.put("abc", Optional.of(5));
    map.put("kk", "xyz");

两者均无法编译。我想知道:

(1)“是什么?”在上面的地图声明中指明?

(2)如何为该“地图”赋予值?

3 个答案:

答案 0 :(得分:8)

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

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

显然,可能性基本上是无限的。如果您具有这种类型的变量,则可以知道它引用的键为String的映射,但您实际上一无所知。特别是,您不知道在get上执行Map时将得到哪种对象。

但是,更重要的是,如果没有某种讨厌的,不安全的投射操作,您将永远无法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,?>变量是非常有限的。如果您只想从映射中读取值,那当然很好。但是不要期望能够在地图中插入任意值,除非您使用其他表达式来引用地图。

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

问题(2)

您可以使用“上限”或“下限”为地图赋予价值。

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

? extends Type   - is used for read access only
? super Type     - is used for write access only.

PECS 简而言之产生(写入权限)-使用扩展,而消耗(读取访问权限)-< strong>使用超级

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));

输出

kk  xyz
abc Optional[5]

Process finished with exit code 0

附加说明

无限制通配符

 List<?> l = new ArrayList<String>();

具有上限的通配符?扩展类型

 List<? extends Exception> l = new ArrayList<RuntimeException>();

下限通配符?超级类型

 List<? super Exception> l = new ArrayList<Object>();

答案 2 :(得分:6)

?是未知类型:您不完全知道代码中的含义。

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

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

map.put("abc", null); // compiles

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

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

// Call with
reAdd(map); // compiles