将对象转换为java中的Comparable

时间:2011-06-30 14:20:22

标签: java generics static-methods

这里我们有通用方法:

public static <T extends Comparable<T>> T[] function(T[] a)
{
    Object[] m = new Object[2];

    /* some work here */

    return (T[]) m;
}

抛出ClassCastException。怎么了?

6 个答案:

答案 0 :(得分:4)

Object数组不是Object的任何子类的数组。您正面临Java中泛型的一个局限性:您无法创建泛型数组。有关可行的方法,请参阅this thread

答案 1 :(得分:3)

Object Comparable。您必须将数组定义为类似的类型。

由于您传递的是数组,因此您可以使用数组的类型:

T[] m = Array.newInstance(a.getClass().getComponentType(), 2);

当然,您必须将Comparable个对象放入其中。

答案 2 :(得分:3)

这里有两个不同的问题。

首先,只需擦除泛型并查看没有泛型的代码(这是它在编译时被删除的内容):

public static Comparable[] function(Comparable[] a)
{
    Object[] m = new Object[2];

    /* some work here */

    return (Comparable[]) m;
}

您无法将实际的运行时类Object[]转换为Comparable[]。周期。

其次,即使您重新编写代码以创建Comparable[]而不是Object[]

public static <T extends Comparable<T>> T[] function(T[] a)
{
    Comparable[] m = new Comparable[2];

    /* some work here */

    return (T[]) m;
}

它仍然无效。它不会在此函数中抛出ClassCastException。但它会在任何调用此函数的代码中抛出它。例如,

String[] foo = function(new String[0]);

会抛出一个ClassCastException,因为当你擦除它时,你会看到编译器为通用方法中出现的东西放置了一个强制转换:

String[] foo = (String[])function(new String[0]);

并且您无法将实际类为Comparable[]的对象强制转换为String[]


当你对那些说过Array.newInstance()是创建运行时已知类的数组的方法的人们说“有什么不同”时。不同之处在于Array.newInstance()返回的对象具有Whatever[]的“实际运行时”类型,其中“Whatever”是传递给它的类对象的类。静态(值的编译时类型)类型是Object[]并不重要;它是重要的实际运行时类型。


当你说“另一个问题是为什么E [] e =(E [])新对象[3]有效”时,你可能在这里遗漏了几点。首先,只有当E被声明为<E><E extends Object>时才有效,即E的下界是对象。第二,这基本上是一个谎言(这在几个地方很方便,比如实现一个通用的集合;但你必须理解为什么它是危险的);而且正式地说,当E不是Object时,你不应该能够从实际类型为Object[]的对象转换为E[]。它只是“有效”,因为在E的范围内,E被删除,所以我们无法检查演员表。但是,如果您尝试将该对象作为E[]返回到外部世界,您将以相同的方式获得ClassCastException。

答案 3 :(得分:2)

嗯,实际上你无法将一组对象强制转换为可比较数组。它没有任何意义。为什么编译器允许这样做?更重要的是,例如,Integer类实现了Comparable,但是你不能将Comparable数组转换为Integer数组。

答案 4 :(得分:0)

T extends Comparable意味着方法参数(在本例中为T)应该从可比范围扩展。所以当你尝试做以下演员

(T[]) m;

您正在尝试将Object []强制转换为Comparable [](或任何扩展Comparable的东西)。

答案 5 :(得分:0)

这就是你想要做的事情:

public static <T extends Comparable<T>> T[] function(final T[] a) {
    final T[] m = (T[]) Array.newInstance(a.getClass().getComponentType(), 2);

    /* some work here */

    return m;
}