这里我们有通用方法:
public static <T extends Comparable<T>> T[] function(T[] a)
{
Object[] m = new Object[2];
/* some work here */
return (T[]) m;
}
抛出ClassCastException
。怎么了?
答案 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;
}