6

我在这里遇到了一个关于带有列表的泛型有界类型的小问题。请帮忙!

模型.java

public class Model {
}

ClassA.java

public class ClassA<T extends Model> {
    private List<T> models;

    public ClassA() {
        models.add((T) new Model());
    }
}

它在这一行给了我一个从 Model 到 T 警告的未经检查的转换:

models.add((T) new Model());

我知道我收到此警告是因为我可以安全地从子类转换为超类,但反之则不行。

有什么办法可以解决这个问题,或者我可以安全地抑制警告吗?

4

3 回答 3

12

你不能做你想做的事。

由于TModel的子类:

  • 每个T都是一个模型
  • 但并非每个Model都是T

具体来说:

如果您通过调用new Model()构造一个新模型,则该实例正是一个模型,而不是任何子类的实例。

Subclass 扩展 Superclass的地方,您永远无法成功地做到这一点:

(Subclass) new Superclass();

因此,您无法成功地将新模型强制转换为 T 的实例。

编译器只会给你一个警告,你可以忽略或禁止,但是当你运行程序并调用add()方法时,你会得到一个ClassCastException 。

于 2013-09-26T15:33:14.420 回答
2

举这个例子

public static void main(String[] args) {
    ClassA<SubModel> models = new ClassA<>();
    for (SubModel model : models.getModels()){
        model.run(); // runtime ClassCastException
    }
}
public static class ClassA<T extends Model> {
    private List<T> models = new LinkedList<>();

    public ClassA() {
        models.add((T)new Model()); // compiles and warns
    }

    public List<T> getModels() {
        return models;
    }
}
public static class SubModel extends Model {
    public void run() {
        System.out.println(this);
    }
}
public static class Model {
}

您添加的对象models是运行时类型Model,它没有run()方法。

当您最终尝试将该对象用作 type 的对象时SubModel,您将ClassCastException像我在main()方法中一样得到 a 。

你真的不应该这样做,即。将父类型对象添加到可能的 suptype 类型对象。

于 2013-09-26T15:35:04.483 回答
-1

您需要在构造函数中添加元素之前初始化列表。我想你可能只复制了相关的代码片段,这就是它被遗漏的原因。

另外,我认为唯一的方法是抑制警告。更多信息只有协方差,逆变:用简单的英语解释协方差,不变性和逆变性?

于 2013-09-26T15:28:07.757 回答