将对象强制转换为 Java 中的 Comparable

Maj*_*imi 5 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;
}
Run Code Online (Sandbox Code Playgroud)

AClassCastException被抛出。它出什么问题了?

new*_*cct 3

你在这里有两个不同的问题。

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

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

    /* some work here */

    return (Comparable[]) m;
}
Run Code Online (Sandbox Code Playgroud)

您无法将其实际运行时类转换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;
}
Run Code Online (Sandbox Code Playgroud)

它仍然不起作用。它不会在此函数内抛出 ClassCastException。但它会把它扔到任何调用这个函数的代码中。例如,

String[] foo = function(new String[0]);
Run Code Online (Sandbox Code Playgroud)

会抛出 ClassCastException,因为当你删除它时,你会看到编译器为泛型方法产生的内容进行了强制转换:

String[] foo = (String[])function(new String[0]);
Run Code Online (Sandbox Code Playgroud)

并且您不能强制转换实际类为Comparable[]to的对象String[]


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


当你说“另一个问题是为什么 E[] e = (E[]) new Object[3] 有效”时,你可能在这里遗漏了几点。首先,只有当 E 被声明为<E>or时才有效<E extends Object>,即 E 的下界是 Object。其次,这基本上是一个谎言(这在很多地方都很方便,比如实现通用集合;但你必须理解为什么它是危险的);从形式上来说,当 E 不是 Object 时,您“不应该”能够从实际类型为Object[]to的对象进行强制转换。E[]它之所以“有效”,是因为在 E 的范围内,E 被擦除,因此我们无法检查强制转换。但是,如果您尝试将该对象作为 an 返回E[]给外界,您将以同样的方式得到 ClassCastException。