2012-03-05 2 views
0

나는 완전히 위풍 당김을 가지고 있으며, 여러분에게 무슨 일이 일어나고 있는지를 알기 위해 그 자세를 취합니다. java 범용 입력을 강제하지 못했습니다.

데이터 구조

Map<String, Object> objectMap 

는 지금 문자열 및 숫자 값을 저장하지만, 향후 더 많은 유형들을 저장할 수있다.

public <T> T get(String variable, T defaultValue) { 
    // returns either the object from the map, or the default if its not in the map. 
    Object value = getObject(variable, defaultValue); 
    logger.debug("default value is of type " + defaultValue.getClass().getName()); 

    // Attempt to get around casting issue 
    if (value instanceof Number) 
    { 
     value = (Number) value; 
    } 
    T ret = (T) value; 
    logger.debug("Variable " + variable + " which is of type " + value.getClass().getName() + " and returning as " + ret.getClass().getName() + " (is number: " + (value instanceof Number) + ")"); 

    return ret; 
} 

그리고 이것은 호출 코드 :

public int getFoo() { return this.<Integer>get("foo", 0); } 

이 내가 로그에서 볼 수있는 출력 :

이것은 내가 그 값을 검색하기 위해 사용하고 기능입니다

default value is of type java.lang.Integer 
Variable foo which is of type java.lang.Long and returning as java.lang.Long (is number: true) 

실패 직전 :

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer 

내가 가장 걱정하는 점은 클래스을 사용하도록 클래스를 강제 설정하려고 시도 했음에도 불구하고 클래스 유형이 Long로 나타나는 것입니다.

나는 뭔가를 놓치고, Java generics의 개념을 위반하고 있습니까? 어떤 도움

+0

처음에는'Map '을 사용해서는 안됩니다. 지도에는 하나의 특정 값 유형이 있어야하며 실제로 함께 코드를 혼합하는 것이 좋습니다. –

+0

이 예외가 발생한 곳에서 더 많은 스택 추적을 보내주십시오. – MJM

+0

지도에 넣은 모양은 어떻게 생겼습니까? –

답변

1

getObject 메서드가 반환하는 값은 java.lang.Long입니다. 로그에 표시됩니다.

제네릭은 마술이 아니며 유형간에 변환하지 않으며 컴파일러가 캐스트로 되돌아가는 단순한 문법적 설탕입니다.그래서 방법 :

public <T> T get(String variable, T defaultValue) 

은 정말 :

this.<Integer>get("foo", 0) 

이 정말 : 따라서

(Integer)this.get("foo", 0) 

ClassCastException이

public Object get(String variable, Object defaultValue) 

get 메소드가 호출 될 때때문에은 Integer이 아니라 Long입니다.

달성하고자하는 것을 정확히 알지 못하면 구체적인 조언을하기가 어렵지만 일반적으로 Map은 처리 할 것으로 예상되는 제네릭 유형을 사용해야합니다. 귀하의 경우 이것은 Integer 또는 Number과 같습니다. Number의 int 값을 정말로 원한다면 (이는 int보다 크면 값이 잘 리므로 의심 스럽습니다) Number.intValue() 메서드를 사용해야합니다.

+0

이것은 내가 찾고 있던 anser였습니다. 나는 이것을 생각했다. 은 캐스팅이되지 않고 함수의 형식이 정수가되도록했습니다. – cyberconte

+0

호출이 실행될 때, 이것. get ("foo", 0) 은 (Integer) this.get ("foo", 0)로 변환됩니다. 그러나 동적으로이 캐스트는 제네릭에 의해 수행되는 것보다 적습니다. 메서드 구현 내에서 캐스트가 더있을 수 있습니다. – DaveFar

0

이에 대한

덕분에 Java 형 소거에 의해 발생합니다. 자바 타이핑은 소스 코드에서만 사용됩니다. 컴파일러는 모든 객체를 형 변환하는 것처럼 코드를 변환합니다. Long 값을 얻으면 Long 값으로 저장한다는 의미입니다.

이 코드는 아무 것도 수행하지 않습니다

if (value instanceof Number) 
{ 
    value = (Number) value; 
} 
0

당신의 백업 맵의 핵심 "foo는"의 값은 롱 타입 분명하다. Long을 정수로 형변환 할 수 없습니다 (두 유형 모두 Number 유형 임에도 불구하고 Object 유형 임).

"Integer"를 강제 실행하려면 "foo"값을 넣을 때 수행해야합니다. 지도에 넣습니다.

관련 문제