我正在编写自己的双链表实现。
我得到方法public <T> T[] toArray(T[] a)
public <T> T[] toArray(T[] a) {
if (a.length < size()) {
T[] array = (T[]) new Object[size()];
Node temp = head;
int currentIndex = 0;
while (currentIndex < size) {
a[currentIndex] = (T) temp.data;
currentIndex++;
temp = temp.next;
}
}
if (a.length > size()) {
a[size] = null;
}
Node temp = head;
for (int i = 0; i < size; i++) {
a[i] = (T) temp.data;
temp = temp.next;
}
return a;
}
我正在用
进行测试 List<String> list = new DoubleLinkedList<String>();
list.add(0, ("0"));
list.add(1, ("1"));
list.add(2, ("2"));
list.add(3, ("3"));
list.add(4, ("4"));
list.add(5, ("5"));
String array[] = list.toArray(new String[6]);
for (int i = 0; i < list.size(); i++) {
System.out.println(array[i]);
}
当我使用String array[] = list.toArray(new String[6]);
或String array[] = list.toArray(new String[7]);
或更高的数字进行测试时,它会起作用。但如果我使用String array[] = list.toArray(new String[5]);
或更低版本进行测试,则无法打印出来。 JUnit抛出ClassCastException。
请帮我解决这个问题。
Edit1:更改了一些不相关的代码。
答案 0 :(得分:0)
此:
T[] array = (T[]) new Object[size()];
错误,因为(例如)Foo[]
和ArrayList<Foo>
之间存在重大差异。使用ArrayList<Foo>
,new ArrayList<Foo>()
创建的实际实例只是ArrayList
; <Foo>
是一些编译器的聪明,可以帮助您跟踪类型,但它会在运行时消失。但是,对于new Foo[10]
,实际创建的实例知道其类型为Foo[]
。例如,就编译器而言,此代码片段完全有效,并在运行时引发ClassCastException
:
Object[] objectArray = new Integer[10];
String[] stringArray = (String[]) objectArray;
而编译器会拒绝带有ArrayList
的类似代码(如果编译器允许,则无法在运行时检查)。
T[] array = (T[]) new Object[size()];
的问题是,T
通常不是Object
(在您的情况下恰好是String
),所以new Object[]
{1}}通常不会是T[]
的实例。
这条有问题的行,ClassCastException
没有出现,因为与泛型相关的类型擦除意味着编译器无法实际检查此行的强制转换;但相反,编译器会在第一次获得机会时插入隐式转换。那就是 - 它隐含地转换了这一行:
String array[] = list.toArray(new String[6]);
到此:
String array[] = (String[]) list.toArray(new String[6]);
失败了,因为当你承诺返回list.toArray
时,你偷偷欺骗Object[]
构建String[]
。
要解决此问题,您需要使用a
的组件类型,并使用一点点反射创建相应数组类型的新实例:
T[] array = (T[]) Array.newInstance(a.getClass().getComponentType(), size());