【问题标题】:Why cant i add a generic type parameter into an ArrayList?为什么我不能将泛型类型参数添加到 ArrayList 中?
【发布时间】:2016-05-14 15:51:50
【问题描述】:

下面第一行注释的代码显示“无法将城市转换为 T”。所以在下一行,我将它转换为 T。 在主程序中编译方法“测试”后,它抛出此异常:“线程“主”中的异常 java.lang.ClassCastException:[Ljava.lang.Object; 无法转换为 [Lapi.xapi.City;”

谁能解释为什么会发生这种情况并在可能的情况下找到解决方案?

提前致谢。

顺便说一句,我需要访问 MyMap 类中 City 类的一些方法,如果真的没有其他方法,我只能使用强制转换。

public class MyMap <T extends City> extends DirectedGraph<City> {

    public void add(T vertex) {
      super.addVertex(vertex);
    }

    public void testing(T vertex) {
      ArrayList<T> x = new ArrayList<>();
    //x.add(super.vertices[0]);        
      x.add((T) super.vertices[0]);
    } 
}

----------------------------------------------- -------------------------------------------------------

信息更新:抱歉信息不足。

这是超类 DirectedGraph:

public class DirectedGraph<T>{

protected final int DEFAULT_CAPACITY=15;
protected T[] vertices;
protected double[][] edges;
protected int numVertices;

public DirectedGraph() {
    this.vertices = (T[]) (new Object[DEFAULT_CAPACITY]);
    this.edges = new double[DEFAULT_CAPACITY][DEFAULT_CAPACITY];
}

public void addVertex(T vertex) {
    this.vertices[this.numVertices] = vertex;
    this.numVertices++;
}
}

【问题讨论】:

  • super.vertices 的类型是什么?
  • 请更正 - DirectedGraph 的构造函数应该是 public DirectedGraph() 而不是 public DiGraph()。此外,ArrayList&lt;T&gt;::addToRear(T t) 方法不存在。听起来您可能想使用Deque&lt;T&gt;,它有一个addLast 方法,可能正在做您想做的事情。
  • 对不起。我只是在这里复制并粘贴并更改了一些代码以简化。 ArrayList::addToRear(T t) 实际上存在,因为我使用的是我自己的 ArrayList 实现。现在我正在使用 Java 的 ArrayList 但问题仍然存在。感谢您的警告。

标签: java generics exception arraylist casting


【解决方案1】:

请考虑作为对您的问题的评论发布的一些更正。

我假设主体看起来像这样:

public static void main(String args[]) {
  new MyMap<City>().testing(new City());
}

那么,至于为什么“转换为T 失败”:

当您实例化new MyMap&lt;City&gt;() 时,它实际上会尝试创建一个City [],但您为其分配了一个Object []。编译器允许这样做,因为使用泛型和类型擦除,此时没有任何问题。编译器还不知道它可以得到除Object [] 以外的任何东西。

可以提供几个解决方案,所有这些都质疑您是否不应该将应用程序的设计带回绘图板上,然后重新考虑。然而,这些是一些选项:

你必须以某种方式传递类型。这可以通过传递 T 类、T 的实例或预先存在的 T 数组来实现。我提供了第二种解决方案,它会使初始化如下所示:

  public DirectedGraph(Class<? super T> class) {
      this.vertices = (T[]) Array.newInstance(clazz, DEFAULT_CAPACITY);
      this.edges = new double[DEFAULT_CAPACITY][DEFAULT_CAPACITY];
  }

然后对于 MyMap,由于父级中的默认构造函数在 DirectedGraph 中消失了(我们添加了一个参数),您必须在 MyMap 中添加一个:

  public MyMap() {
    super(City.class);
  }

通过这些代码更改,我更进一步。但是因为我的初始化逻辑不完整,或者因为它有其他问题,会弹出下一个不相关的错误。

我想链接以下帖子:

【讨论】:

  • 谢谢。它真的很好用。你是天才乔德。再次非常感谢你:)
【解决方案2】:

您将 T 限制为 City 的子类型,我猜 super.vertices 要么返回城市的超类型,要么返回 Object。 通过强制转换为 T,您是在告诉编译器“相信我,我知道它是 City 的子类型”

【讨论】:

    猜你喜欢
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-01
    相关资源
    最近更新 更多