有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java泛型问题与数组

对不起,我想不出更简洁的标题了

我的问题是为什么下面的代码可以工作:

public abstract class TObjectPool<T> {
protected Object[] availableObjects;

TObjectPool(int size){
    availableObjects = new Object[size];
}

protected class RenderElementPool extends TObjectPool<RenderElement>{
    @Override
    public void fill() {
        for (int i = 0; i < capacity; i++) {
            availableObjects[i] = new RenderElement();   
        }
    }
}

当无法使对象数组成为通用数组时,如下所示:

public abstract class TObjectPool<T> {
protected T[] availableObjects;

TObjectPool(int size){
    availableObjects = (T[]) new Object[size];
}

当可用对象[i]=新渲染()时;在后一个示例中,我得到一个ClassCastException。我理解为什么在第一个例子中它有效,但在第二个例子中它不起作用。可用对象应该是一个渲染数组,我正在尝试给它一个渲染。我遗漏了哪些关键信息

谢谢你的帮助

更新

非常感谢您的回复。我以为我明白了,但我又一次弄糊涂了:

如果我添加该函数:

public void add(int index, T object){
    availableObjects[index] = object;
}

到TObjectPool类。它将愉快地与T[]数组一起工作

因此,新的TObjectPool和子类pool如下所示:

public abstract class TObjectPool<T> {
T[] availableObjects;

TObjectPool(int size){
    availableObjects = (T[])new Object[size];
    capacity = size;
    count = capacity;
    fill();
}

public void add(int index, T object){
    availableObjects[index] = object;
}

protected class RenderElementPool extends TObjectPool<RenderElement>{
@Override
public void fill() {
    for (int i = 0; i < capacity; i++) {
        add(i, new RenderElement()); //this works
        //availableObjects[i] = new RenderElement(); //this gives an exception          
    }
}
}

在阅读了你的回答后,我知道我现在可以如何回避这个问题,但我很好奇。有人能解释一下这种怪癖吗

再次感谢


共 (3) 个答案

  1. # 1 楼答案

    强制转换失败,因为Object[]是所有T的T[]的超类,但不是除Object以外的任何T的子类型

    如果在运行时有可用的Class<T>,则可以使用^{}创建T[]

  2. # 2 楼答案

    Java中的数组不是泛型的,因此不能将Java泛型应用于数组。特别是,在构造函数中从Object[]强制转换到T[]是错误的,这很可能是错误的原因

    知道了这一点,当需要在泛型类中实例化非泛型的东西时,可以使用相同的技巧:传递特定的类对象

    TObjectPool(int size, Class<T> klass) {
        availableObjects = Array.newInstance(klass, size);
    }
    ...
    protected class RenderElementPool extends TObjectPool<RenderElement>{
        // Pass the class object to super constructor
        public RenderElementPool(int size) {
           super(size, RenderElement.class);
        }
        ...
        @Override
        public void fill() {
            for (int i = 0; i < capacity; i++) {
                availableObjects[i] = new RenderElement();   
            }
        }
    }