2010-06-21 5 views
1

작은 유틸리티 메소드를 작성했지만 항상 ClassCastException을 생성합니다. 그 이유는 무엇입니까? 그것을 고치는 방법? 당신은 더 나은 System.arraycopy(..)을 사용하십시오 String[] ar = new Object[1];배열의 subList - 일반 유형으로 캐스팅 할 때 ClassCastException

시도 -

java.lang.ClassCastException: [Ljava.lang.Object; 
at org.robert.distance.framework.FacadeTest.testSubArray(FacadeTest.java:48) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:592) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
+0

스택 추적을 게시 할 수 있습니까? 도움이 될 것입니다. –

답변

7

사용 Arrays#copyOfRange()

<T> T[] subArray(int begin, int end, T[] array) { 
    return Arrays.copyOfRange(array, begin, end); 
} 

은 지옥, 심지어하게 전체 subArray() 방법 불필요한 : 그것은 JDK 1.6 필요한 경우에만. 어떤 이유로 아직 여기에 있지 않다면 여기에 관련성이 있습니다.

public static <T> T[] copyOfRange(T[] original, int from, int to) { 
    int newLength = to - from; 
    if (newLength < 0) throw new IllegalArgumentException(from + " > " + to); 
    T[] copy = (T[]) Array.newInstance(original.getClass().getComponentType(), newLength); 
    System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); 
    return copy; 
} 
+2

나는이 유용한 방법을 잊어 버리는 경향이있다 :) (+1) – Bozho

4

T[]Object[]되지 않습니다 :

<T> T[] subArray(int begin, int end, T[] array) { 
    int size = end - begin; 
    Object[] newArray = new Object[size]; 
    for (int i = 0; i < size; i++) { 
     newArray[i] = array[begin + i]; 
    } 
    return (T[]) newArray; 
} 

여기 스택 추적입니다. 그리고 새로운 배열을 생성하므로이 두 가지 방법을 결합 Array.newInstance(newType.getComponentType(), newLength);를 사용 Arrays.copyOf 유틸리티 방법은 당신의 목표

업데이트를 달성하기 위해 : 코멘트에 주목하고, BalusC의 대답에 따라, Arrays.copyOfRange(..)

+1

또 다른 옵션은'Arrays.copyOfRange (...)'를 사용하는 것인데, 아마도'System.arraycopy (...) '보다 약간 나쁠 수도 있습니다. – MarcoS

+0

@MarcoS :'Arrays.copyOfRange (...)'는 자바에서만 사용할 수 있습니다 1.6 + – newacct

+0

@newacct : 네 말이 맞아.하지만 질문은 Java 버전 – MarcoS

5

내가 의심 이미있는 문제는 Object[]입니다. new Object[size]을 사용하는 대신 올바른 유형의 새 배열을 만들어야합니다. 이를 수행하는 한 가지 방법은 Array.newInstance(Class<?> componentType, int length)을 사용하는 것입니다. 같은

뭔가 :

<T> T[] subArray(int begin, int end, T[] array) { 
    int size = end - begin; 
    T[] newArray = (T[])Array.newInstance(array.getClass().getComponentType(), size); 
    for (int i = 0; i < size; i++) { 
     newArray[i] = array[begin + i]; 
    } 
    return newArray; 
} 
+0

에 대한 어떠한 제한도 언급하지 않았다. 배열은 어떻게 구성 요소 유형이 무엇인지 알 수 있을까? – OscarRyz

+0

@Sup : 정확한 '클래스'는 런타임 중에 항상 알려집니다. – BalusC

1

예, 그것은 아주 간단합니다. Object[] 배열을 만든 다음 T[]으로 전송 중입니다. TObject이 아니면이 캐스트가 실패합니다.

제네릭과 배열은 실제로 잘 어울리지 않습니다. ILMTitan에 따르면 Array.newInstance을 사용할 수 있지만 호출자가 Class<T>의 인스턴스를 메서드에 전달하도록해야합니다. System.arrayCopy을 사용하는 것이 더 나은 접근 방법이 될 수 있지만 정확하게 여기있는 것처럼 보입니다.

관련 문제