在java中将对象强制转换为可比较对象

在java中将对象强制转换为可比较对象,java,generics,static-methods,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; } String[] foo = (String[])function(new String[0]); 公共静态T[]函数(T[]a) { Object[]m=新对

这里我们有一个通用方法:

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

    /* some work here */

    return (T[]) m;
}
String[] foo = (String[])function(new String[0]);
公共静态T[]函数(T[]a)
{
Object[]m=新对象[2];
/*这里有些工作*/
返回(T[])m;
}

抛出一个
ClassCastException
。有什么问题吗?

对象数组不是对象任何子类的数组。您正面临Java中泛型的一个限制:无法创建泛型数组。有关有效的方法,请参阅。

对象
不可比。必须将数组定义为可比较的类型

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

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

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

T扩展compariable意味着方法参数(在本例中为T)应该从compariable扩展。所以当你试着做下面的演员时

(T[]) m;

您正试图将对象[]强制转换为可比较[](或扩展为可比较的任何对象)。

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

这就是您要执行的操作:

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;
}
公共静态T[]函数(最终T[]a){
最终的T[]m=(T[])数组.newInstance(a.getClass().getComponentType(),2);
/*这里有些工作*/
返回m;
}

这里有两个不同的问题

首先,只需删除泛型并查看没有泛型的代码(这就是编译时删除的代码):

不能将实际运行时类为
object[]
的对象强制转换为
Comparable[]
。句号

其次,即使您重新编写代码是为了创建一个
可比[]
而不是
对象[]

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

    /* some work here */

    return (T[]) m;
}
将抛出ClassCastException,因为当您删除它时,您会看到编译器对泛型方法产生的内容进行强制转换:

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

    /* some work here */

    return (T[]) m;
}
String[] foo = (String[])function(new String[0]);
并且不能将实际类为
Comparable[]
的对象强制转换为
String[]


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



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

确切的堆栈跟踪是什么?另外,发布引发异常的代码。您正在以C#泛型的方式使用Java泛型。@Elite-我真诚地怀疑是否存在堆栈跟踪或异常,因为代码无法编译。但我们可以编写这样的代码:
E[]array=(E[])new Object[10]//虽然is给出了警告,但它与代码中的警告相同,不是吗?如果您使用
-Xlint:unchecked
编译它,您将得到警告。除非
E
Object
,否则您不会对运行时的结果感到满意。那么什么是尊重呢
Array.newInstance
正在创建新数组并返回
对象[]
,然后将其强制转换为
T[]
。这就是我在代码中所做的。重要的部分是在数组中放置可比较的对象。newInstance只保存了一些强制转换。@此处使用的Majid Array.newInstance将创建与输入相同类的新数组。在Java中,不同组件类型的数组之间存在差异,Object[]和Comparable[]是两个不同的类。如果在两个不同类型的数组上比较getClass的结果,很容易看到这一点。由于对象与泛型T的类型不同(而且永远不可能是),所以您将始终得到一个ClassCastException。对象是所有类的超类。为什么我们不能给它分配不同类的数组?另一个问题是为什么
E[]E=(E[])新对象[3]
有效,但是
Object[]o=新对象[3]
然后
E[]E=(E[])o不起作用?他们也在这样做吗?不是吗?