java : (String []) List.toArray ()는 ClassCastException을 제공합니다.


107

다음 코드 (Android에서 실행)는 항상 세 번째 줄에 ClassCastException을 제공합니다.

final String[] v1 = i18nCategory.translation.get(id);
final ArrayList<String> v2 = new ArrayList<String>(Arrays.asList(v1));
String[] v3 = (String[])v2.toArray();

v2가 Object [0]이고 문자열이있을 때도 발생합니다. 이유는 무엇입니까?


Covariance 및 Contravariance에 대해 읽을 수 있습니다.- en.wikipedia.org
wiki

T가 인스턴스화를위한 팩토리 메소드와의 인터페이스 인 경우는 어떻습니까?
sebaj 2011 년

2
@LaceCard-이것은 공분산 / 반 분산과 매우 간접적으로 만 관련이 있습니다. 실제 문제는 이것이 toArray()메서드 의 지정된 동작의 직접적인 결과라는 것입니다.
Stephen C

답변:


249

이것은 당신이 사용할 때

 toArray() 

String []으로 형변환 할 수없는 Object []를 반환합니다 (내용이 String 인 경우에도). 이는 toArray 메서드가

List 

그리고 아닙니다

List<String>

제네릭은 소스 코드 일 뿐이며 런타임에는 사용할 수 없으므로 생성 할 배열 유형을 결정할 수 없습니다.

사용하다

toArray(new String[v2.size()]);

올바른 종류의 배열 (String [] 및 올바른 크기)을 할당합니다.


3
사촌 제네릭, 그 이유는
Kaleb Brasee 2011-04-16

2
@Kaleb-사실이 아닙니다. 아니면 적어도 그것은 원래의 이유가 아닙니다. toArray컬렉션 클래스 전에 존재 방법이 일반적이었다.
Stephen C

10
이것은 올바른 해결책이지만 올바른 설명은 아닙니다. Object []는 언어 기능이기 때문에 Double []로 캐스팅 할 수 없습니다. Generics와 관련이 없습니다. 실제로 Double이라고 가정하고 Object를 Double로 캐스팅 할 수 있습니다. 따라서 논리적으로 배열로 동일한 작업을 수행 할 수 있지만 이는 단순히 언어의 일부가 아닙니다. Object를 Double로 캐스트하면 Object가 실제로 Double인지 확인하는 런타임 검사가 있습니다. Double을 Object로 캐스트하면 Object가 Double의 상속 계층 구조에 있으므로 런타임 검사가 없습니다.
KyleM 2013 년

5
IntelliJ에서이 작업을 수행 할 때 toArray(new String[0])대신 사용하라는 경고가 표시됩니다 . "사전 크기 배열 을 사용 하는 이전 Java 버전에서는 적절한 크기의 배열을 생성하는 데 필요한 리플렉션 호출이 매우 느리기 때문에 권장되었습니다. 그러나 OpenJDK의 최신 업데이트 이후 6이 호출이 내재되어 빈 어레이 버전의 성능이 동일하고 때로는 더 나아졌습니다. 또한 사전 크기 어레이를 전달하는 것은 sizetoArray호출 사이에 레이스가 가능하므로 동시 수집에 위험합니다 . "
Mikepote

35

당신은 잘못 사용하고 있습니다 toArray()

Java의 제네릭은 대부분 구문 설탕이라는 것을 기억하십시오. ArrayList는 실제로 모든 요소가 문자열이라는 것을 알지 못합니다.

문제를 해결하려면으로 전화하십시오 toArray(T[]). 귀하의 경우에는

String[] v3 = v2.toArray(new String[v2.size()]);

일반화 된 형식 toArray(T[])은을 반환 T[]하므로 결과를 명시 적으로 캐스팅 할 필요가 없습니다.


1
String[] v3 = v2.toArray(new String[0]); 

또한 트릭을 수행하므로 올바른 ArrayType이 메소드에 제공되면 더 이상 캐스트 할 필요가 없습니다.


0
String[] str = new String[list.size()];
str = (String[]) list.toArray(str);

이렇게 사용하십시오.


1
부디! 코드를 포맷하세요! "ctrl + k"를 눌러 모두 선택하거나 코드의 첫 글자 앞에 "`"를 추가하고 마지막에 다른 글자를 추가합니다. 답변을 작성할 때 상단의 도움말에서 "{}"를 선택할 수도 있습니다!
MK
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.