나는 버그처럼 보이는 자바의 이상한 행동을 보았습니다. 그렇지? 객체가 K
의 인스턴스가 아니더라도 객체를 일반 유형 (예 : K
)으로 캐스팅하면 ClassCastException
이 발생하지 않습니다. 다음은 그 예이다 :Java에서 일반 유형으로 변환하면 ClassCastException이 발생하지 않습니까?
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!!
}
}
업데이트 : 감사합니다 당신의 도움이 답변의 Andrzej 도일 클리 터스하고. 그 중 하나만 받아 들일 수 있기 때문에 Andrzej Doyle's answer을 수락 할 것입니다. 왜냐하면 그것이 제가 생각하는 해결책으로 이끌었 기 때문입니다. 도입니다. 한 줄짜리 작은지도를 초기화하는 좀 더 나은 방법이라고 생각합니다.
/**
* 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;
}
그리고는 당신은 다음과 같이 호출 :
Map<String,Number> m = MapBuilder.build(String.class, Number.class, "L", 11, "W", 17, "H", 0.001);
필자는'map = (key1 => key1 => val1, key2 =>)와 같은 일을 할 수있는 다른 언어 (예 : Perl/PHP/Javascript)와 같이 일직선으로 맵을 초기화 할 수있는 형식적인 방법을 원했습니다. val2, etc.); – Kip
네, 그럴 수 없습니다. 배열에는 컴파일 타임 타입 정보가없고 일반 매개 변수에는 런타임 타입 정보가 없습니다. 'Class'매개 변수를 전달하는 것은 컴파일 타임과 런타임 검사를 함께 묶을 수있는 유일한 방법입니다. –