Java泛型类强制转换异常

Java泛型类强制转换异常,java,generics,comparable,Java,Generics,Comparable,我试图创建一个处理可比较数据的类。我归结为最简单的代码,当我试图实例化这个类时,它会给出一个错误。我得到了一些编译警告(未经检查的强制转换),但是当我运行这个程序时,它会抛出一个类强制转换异常。我确实看了一些关于这个话题的其他问题,但没有发现有用的东西 public class GD<Item extends Comparable<Item>> { private Item[] data; private final int MAX_SIZE = 200;

我试图创建一个处理可比较数据的类。我归结为最简单的代码,当我试图实例化这个类时,它会给出一个错误。我得到了一些编译警告(未经检查的强制转换),但是当我运行这个程序时,它会抛出一个类强制转换异常。我确实看了一些关于这个话题的其他问题,但没有发现有用的东西

public class GD<Item extends Comparable<Item>> {
   private Item[] data;
   private final int MAX_SIZE = 200;
   public GD() {
      data = (Item[]) new Object[MAX_SIZE];
   }

   public static void main(String[] args) {
     GD<String> g = new GD<String>();
   }
}
公共类GD{
私有项[]数据;
私人最终整数最大值=200;
公共GD(){
数据=(项目[])新对象[最大大小];
}
公共静态void main(字符串[]args){
GD g=新的GD();
}
}
问题在于:

data = (Item[]) new Object[MAX_SIZE];
您正在实例化一个
对象
数组,然后尝试将其转换为
数组,这会引发异常,因为
对象
没有扩展
类,因为它没有实现
可比
。您想要的是:

data = new Item[MAX_SIZE];
但是您不能这样做,因为
Item
是泛型类型。如果要动态创建此类型的对象(或对象数组),需要将
对象传递给GD类的构造函数:

import java.lang.reflect.Array;

public class GD<Item extends Comparable<Item>> {
   private Item[] data;
   private final int MAX_SIZE = 200;
   public GD(Class<Item> clazz) {
      data = (Item[]) Array.newInstance(clazz, MAX_SIZE);
   }

   public static void main(String[] args) {
     GD<String> g = new GD<String>(String.class);
   }
}
import java.lang.reflect.Array;
公共类GD{
私有项[]数据;
私人最终整数最大值=200;
公共GD(课堂){
data=(Item[])Array.newInstance(clazz,MAX_SIZE);
}
公共静态void main(字符串[]args){
GD g=新的GD(String.class);
}
}
问题在于:

data = (Item[]) new Object[MAX_SIZE];
您正在实例化一个
对象
数组,然后尝试将其转换为
数组,这会引发异常,因为
对象
没有扩展
类,因为它没有实现
可比
。您想要的是:

data = new Item[MAX_SIZE];
但是您不能这样做,因为
Item
是泛型类型。如果要动态创建此类型的对象(或对象数组),需要将
对象传递给GD类的构造函数:

import java.lang.reflect.Array;

public class GD<Item extends Comparable<Item>> {
   private Item[] data;
   private final int MAX_SIZE = 200;
   public GD(Class<Item> clazz) {
      data = (Item[]) Array.newInstance(clazz, MAX_SIZE);
   }

   public static void main(String[] args) {
     GD<String> g = new GD<String>(String.class);
   }
}
import java.lang.reflect.Array;
公共类GD{
私有项[]数据;
私人最终整数最大值=200;
公共GD(课堂){
data=(Item[])Array.newInstance(clazz,MAX_SIZE);
}
公共静态void main(字符串[]args){
GD g=新的GD(String.class);
}
}

很简单:
对象
不实现
可比
,但您强制执行
项扩展可比
。因此,不能将
对象[]
强制转换为
项[]

为了避免创建泛型类型
Item
的数组的问题,我们可以看看Java的实现。此处,支持数组的类型为
Object
,只能通过以下方式访问:

由于只允许插入
s,因此只能返回
s,因此永远不会有
类异常


关于代码的一些注释:通常,类型参数使用
T
U
S
。如果使用类似于
Item
,可能会将类型参数与acutal类混淆。

很简单:
对象
不实现
可比
,但您强制执行
Item扩展可比
。因此,不能将
对象[]
强制转换为
项[]

为了避免创建泛型类型
Item
的数组的问题,我们可以看看Java的实现。此处,支持数组的类型为
Object
,只能通过以下方式访问:

由于只允许插入
s,因此只能返回
s,因此永远不会有
类异常

关于代码的一些注释:通常,类型参数使用
T
U
S
。如果您使用类似于
Item
,可能会将类型参数与acutal类混淆。

强制转换
(Item[])
不会根据
Item[]
检查对象的运行时类型,因为运行时不知道
Item
是什么;相反,它检查
项[]
的擦除情况,该项为
可比[]
(因为
可比
是对
的擦除)。实际运行时类为
object[]
的对象不是
Comparable[]
的实例,因此它会导致
ClassCastException
。这就是为什么要这么做

data = (Item[]) new Comparable[MAX_SIZE];
将使例外消失

因此,有两种方法可以实现这一点:

  • 类型理论上是“安全”的方式,即使用固定的非特定数组类型,如
    Object[]
    Comparable[]
    作为
    数据
    变量的编译时类型。这样,您就可以创建相同运行时类型的数组对象,并安全地将其分配给变量,而无需进行不安全的强制转换。但是,当需要从数组中取出某些内容并将其作为泛型类型返回时,必须执行显式(未选中)强制转换:

强制转换
(Item[])
不会根据
Item[]
检查对象的运行时类型,因为运行时不知道
Item
是什么;相反,它检查
项[]
的擦除情况,该项为
可比[]
(因为
可比
是对
的擦除)。实际运行时类为
object[]
的对象不是
Comparable[]
的实例,因此它会导致
ClassCastException
。这就是为什么要这么做

data = (Item[]) new Comparable[MAX_SIZE];
将使例外消失

因此,有两种方法可以实现这一点:

  • 类型理论上是“安全”的方式,即使用固定的非特定数组类型,如
    Object[]
    Comparable[]
    作为
    数据
    变量的编译时类型。这样就可以创建一个数组对象