I have come across a strange behavior of Java that seems like a bug. Is it? Casting an Object to a generic type (say, K
) does not throw a ClassCastException
even if the object is not an instance of K
. Here is an example:
import java.util.*;
public final class Test {
private static<K,V> void addToMap(Map<K,V> map, Object ... vals) {
for(int i = 0; i < vals.length; i += 2)
map.put((K)vals[i], (V)vals[i+1]); //Never throws ClassCastException!
}
public static void main(String[] args) {
Map<String,Integer> m = new HashMap<String,Integer>();
addToMap(m, "hello", "world"); //No exception
System.out.println(m.get("hello")); //Prints "world", which is NOT an Integer!!
}
}
Update: Thanks to cletus and Andrzej Doyle for your helpful answers. Since I can only accept one, I'm accepting Andrzej Doyle's answer because it led me to a solution that I think isn't too bad. I think it's a little better way of initializing a small Map in a one-liner.
/**
* Creates a map with given keys/values.
*
* @param keysVals Must be a list of alternating key, value, key, value, etc.
* @throws ClassCastException if provided keys/values are not the proper class.
* @throws IllegalArgumentException if keysVals has odd length (more keys than values).
*/
public static<K,V> Map<K,V> build(Class<K> keyClass, Class<V> valClass, Object ... keysVals)
{
if(keysVals.length % 2 != 0)
throw new IllegalArgumentException("Number of keys is greater than number of values.");
Map<K,V> map = new HashMap<K,V>();
for(int i = 0; i < keysVals.length; i += 2)
map.put(keyClass.cast(keysVals[i]), valClass.cast(keysVals[i+1]));
return map;
}
And then you call it like this:
Map<String,Number> m = MapBuilder.build(String.class, Number.class, "L", 11, "W", 17, "H", 0.001);