今天,我发现一个能够put
的对象在一个现有的Map
中即使对象不能被转换为正确的类型。在初始化的Map中放置不一致类型的对象 - 预期的和合法的?
首先,让我先用一个简单的例子:
Map<Integer, String> myMap = new HashMap<>(); //plain old hashmap
myMap.put(9,"star"); //no problem
myMap.put(10, 1.2); //Incompatible type, the compiler yells
Map<Integer, Double> aMap = (Map<Integer, Double>) myMap; //Cannot cast, the compiler yells
到目前为止,一切都在意料之中的,因为你应该不能够把不一致类型的对象为已构建的地图。现在让我们来看看这个:
public class NoRulesForMe {
static Object theRing;
public static void main(String[] args){
Map<Integer, String> myMap = new HashMap<>();
myMap.put(9,"star");
Map<Integer, Double> myMapMorphed = castWildly(myMap);
myMapMorphed.put(99, 3.14);
System.out.println(myMapMorphed.get(9)); //"star", as we put in
System.out.println(myMapMorphed.get(99)); //3.14, as we put in
}
public static <T> T castWildly(Object value){
theRing = value;
T morphed = (T) theRing;
return morphed;
}
}
我很惊讶,这并没有导致运行时错误 - 如何地图实现这一目标,并且是在JLS或API指定了此行为,因此可以被信赖的?
我想问的原因是我在生产代码中看到了一个(更多参与的)版本,并且我怀疑,即使这可能是混乱和臭味,它是否可以保证以功能方式工作。任何输入将不胜感激。
你需要谷歌“键入擦除”。 –
这在Java的泛型实现中是_inherent_。 –
@LouisWasserman您可否详细说明* Java的泛型中固有的*是什么?编译器没有抱怨,我并不感到惊讶。但是我认为更大的问题是Java如何允许“Double”可以存储为“String”。 – flow2k