Java / 泛型 / ClassCastException

Java / Generics / ClassCastException

我有一个 LinkedList<T>,其中包含 Object toArray() 方法:

public Object[] toArray()
{

    Object[] array = new Object[size];

    int c=0;
    for(Node<T> i = first;i != null;i=i.next)
    {
        array[c++] = i.data;
    }

    return array;
}

我想用通用方法对 LinkedList 进行排序:<T extends Comparable> void sort (List<T> list)。要对列表进行排序,我必须在此方法中将它们表示为数组:

T[] elements = (T[])list.toArray();`

然而,我在这一行得到 ClassCastException,我不知道为什么。由于该方法的泛型类型等同于返回数组中元素的运行时类型,因此此转换不是谎言!

您应该改用 T[] toArray(new T[list.size()])。不用投。

toArray()returnsObject[]。类型信息丢失,您无法将其转换回 T[]。如果要保留类型信息,可以使用以下内容。然后你给这个方法一个被填充的预定义数组。如果您什么都不给 - toArray 将创建一个新的 Object[].

T[] elements = list.toArray(new T[list.size()]);

只是填充一个数组(另一种写法):

T[] elements = new T[list.size()];
list.toArray(elements);

或者如果您使用 Java 8:

T[] elements = list.stream().toArray(T[]::new);

方法 LinkedList.toArray() 创建了一个类型为 Object[] 的新数组。它不会创建 T[] 类型的新数组。这很重要,因为即使数组只包含 T 的实例,也不能将数组分配给类型 T[] 的变量,因为数组本身具有类型 Object[]。您可以使用以下代码重现此错误:

String[] array = (String[]) new Object[0];

如果我没理解错的话,你想把列表转换成数组,以便能够实现自己的搜索功能。给定一个 List<T>,它包含 T 类型的元素,您希望将此列表转换为 T[] 类型的数组。但是,您不能简单地调用 new T[list.size()],因为 Java 在编译时会丢失通用类型信息。要创建正确类型的数组,您需要使用反射方法 Array.newInstance().

这是一个例子:

@SuppressWarnings("unchecked")
private <T extends Comparable<T>> void sort(List<T> list, Class<T> clazz) {
    T[] array = list.toArray((T[]) Array.newInstance(clazz, list.size()));
    // sort array and write result to the list
}

这里是用法:

    List<String> list = new LinkedList<String>();
    // populate the list
    sort(list, String.class);
    System.out.println(list); // -> the sorted list