내 봄 응용 프로그램 컨텍스트 파일에는 다음과 같은 것이 있습니다.
<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
<entry key="some_key" value="some value" />
<entry key="some_key_2" value="some value" />
</util:map>
Java 클래스에서 구현은 다음과 같습니다.
private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
이클립스에서는 다음과 같은 경고가 표시됩니다.
유형 안전 : Object에서 HashMap으로 캐스트되지 않은 캐스트
내가 뭘 잘못 했어? 문제를 어떻게 해결합니까?
답변
글쎄, 우선, 당신은 새로운 HashMap
창조 호출로 기억을 낭비하고 있습니다. 두 번째 줄은 생성 된이 해시 맵에 대한 참조를 완전히 무시하여 가비지 수집기에서 사용할 수있게합니다. 따라서 그렇게하지 마십시오.
private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
둘째, 컴파일러는 객체가 HashMap
검사인지 여부를 확인하지 않고 객체를 캐스팅한다고 불평합니다 HashMap
. 그러나 당신이해야 할 경우에도 :
if(getApplicationContext().getBean("someMap") instanceof HashMap) {
private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}
여전히이 경고가 표시 될 것입니다. 문제는 getBean
returns Object
이므로 유형이 무엇인지 알 수 없습니다. 그것을 HashMap
직접 변환해도 두 번째 경우에는 문제가 발생하지 않을 것입니다 (첫 번째 경우에는 경고가 없을 것입니다 .Java 컴파일러에 Java 5에 대한 경고가 얼마나 실용적인지 잘 모르겠습니다). 그러나 당신은 그것을로 변환하고 HashMap<String, String>
있습니다.
HashMaps는 실제로 객체를 키로 사용하고 객체를 값으로 갖는 맵 HashMap<Object, Object>
입니다. 따라서 Bean을 얻을 때 리턴되는 비 제네릭 표현에 오브젝트가 HashMap<String, String>
있을 수 있기 때문에 Bean으로 표시 될 수 있다는 보장이 없습니다 HashMap<Date, Calendar>
.
코드가 컴파일되고 String value = map.get("thisString");
오류없이 실행할 수 있으면이 경고에 대해 걱정하지 마십시오. 그러나 맵이 문자열 키에 대한 문자열 키로 완전히 구성되지 않은 경우, ClassCastException
제네릭이이 경우 발생하는 것을 막을 수 없기 때문에 런타임에 얻을 수 있습니다.
답변
문제는 캐스트 런타임 검사입니다 -하지만 형의 삭제로 인해 런타임에 실제로 사이에는 차이가 없습니다 HashMap<String,String>
및 HashMap<Foo,Bar>
기타에 Foo
와 Bar
.
사용 @SuppressWarnings("unchecked")
하고 코를 누르고 있습니다. 아, 그리고 자바의 제네릭에 대한 캠페인 🙂
답변
위의 메시지에서 알 수 있듯이 목록은 a List<Object>
와 a List<String>
또는 a로 구별 할 수 없습니다 List<Integer>
.
비슷한 문제 로이 오류 메시지를 해결했습니다.
List<String> strList = (List<String>) someFunction();
String s = strList.get(0);
다음과 같이 :
List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);
설명 : 첫 번째 유형 변환은 오브젝트가 보유한 유형을 고려하지 않고 목록인지 확인합니다 (목록 레벨에서 내부 유형을 확인할 수 없기 때문에). 컴파일러는 List에 일종의 객체가 포함되어 있음을 알고 있으므로 두 번째 변환이 필요합니다. 그러면 액세스 할 때 List의 각 개체 유형이 확인됩니다.
답변
경고는 바로 그것입니다. 경고. 때때로 경고는 관련이 없으며 때로는 그렇지 않습니다. 컴파일러가 문제가 될 수 있지만 그렇지 않을 수도 있다고 생각하는 것에주의를 기울이는 데 사용됩니다.
캐스트의 경우이 경우 항상 경고가 표시됩니다. 특정 캐스트가 안전하다고 확신하는 경우 줄 바로 앞에 다음과 같은 주석을 추가하는 것이 좋습니다 (구문을 잘 모르겠습니다).
@SuppressWarnings (value="unchecked")
답변
getBean이 오브젝트 참조를 리턴하고 올바른 유형으로 캐스트하기 때문에이 메시지가 표시됩니다. Java 1.5는 경고를 표시합니다. 이것이 이와 같은 코드로 Java 1.5 이상을 사용하는 특성입니다. 스프링은 typesafe 버전을 가지고 있습니다
someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");
할 일 목록에 있습니다.
답변
실제로 경고를 제거하려면 일반 클래스에서 확장되는 클래스를 작성해야합니다.
예를 들어, 사용하려는 경우
private Map<String, String> someMap = new HashMap<String, String>();
당신은 같은 새로운 클래스를 만들 수 있습니다
public class StringMap extends HashMap<String, String>()
{
// Override constructors
}
그런 다음 사용하면
someMap = (StringMap) getApplicationContext().getBean("someMap");
컴파일러는 (더 이상 일반적인) 유형이 무엇인지 알고 있으며 경고는 없습니다. 이것은 항상 완벽한 해결책은 아니지만 일부는 이런 종류의 제네릭 클래스의 목적을 무효화한다고 주장 할 수도 있지만 제네릭 클래스의 동일한 코드를 모두 재사용하고 있으며 컴파일 타임에 어떤 유형을 선언하고 있습니까? 사용하고 싶습니다.
답변
확인되지 않은 경고를 피하기위한 해결책 :
class MyMap extends HashMap<String, String> {};
someMap = (MyMap)getApplicationContext().getBean("someMap");