2010-06-21 43 views
1

我写了一个小的实用程序方法,但它总是会产生一个ClassCastException,任何想法为什么?以及如何解决它?数组的子列表 - ClassCastException当转换为通用类型

<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; 
} 

这里的堆栈跟踪:

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

您可以发布堆栈跟踪吗?这将有所帮助。 – 2010-06-21 15:56:44

回答

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 2010-06-21 16:11:39

4

T[]Object[] - 尝试String[] ar = new Object[1];

你最好使用System.arraycopy(..)。而Arrays.copyOf使用Array.newInstance(newType.getComponentType(), newLength);创建一个新的数组,所以这两种方法相结合的实用方法来实现自己的目标

更新:正如在评论中指出,在BalusC的回答,已经有Arrays.copyOfRange(..)

+1

另一种选择是使用'Arrays.copyOfRange(...)',可能表现得比'System.arraycopy(...)要差一些'...' – MarcoS 2010-06-21 16:11:33

+0

@MarcoS:'Arrays.copyOfRange(...)'只能用于Java 1.6+ – newacct 2010-06-22 02:27:41

+0

@newacct:你是对的,但是这个问题没有说明对Java版本的限制 – MarcoS 2010-06-22 06:20:35

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 2010-06-21 16:19:48

+0

@Sup:确切的'Class'在运行时总是已知的。 – BalusC 2010-06-21 17:36:24

1

是的,这是非常简单的。您正在创建一个Object[]数组,然后将其转换为T[]。如果T不是Object,则此投射将失败。

泛型和数组的混合不太好。正如ILMTitan所说,您可以使用Array.newInstance,但是您必须让主叫方将Class<T>的实例传入您的方法中。虽然更好的方法是使用System.arrayCopy,因为这看起来正是你在这里做的。

相关问题