所以我有一个未知类型的对象的ArrayList扩展Entity(我自己的类;不要混淆java.swing.text.html.parser.Entity),原因与此问题无关。
private ArrayList<? extends Entity> listedEntities = new ArrayList<>();
这是在一个类中,在其构造函数中接收一个String并将其分配给字段entityClass。
在某些时候,我正在执行以下代码:
Class<?> clazz = Class.forName(this.entityClass);
Object newEntity = clazz.newInstance();
listedEntities.add(newEntity);
当然,这并不起作用,因为ArrayList期望一个类的对象扩展Entity而newEntity是Object。所以首先要尝试铸造。
listedEntities.add(Class.forName(this.entityClass).cast(newEntity));
也不起作用。几分钟后没有找到答案我在这里打字。
例外:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method add(capture#8-of ? extends Entity) in the type ArrayList<capture#8-of ? extends Entity> is not applicable for the arguments (capture#9-of ?)
答案 0 :(得分:3)
一个简单的解决方案是这样的:
将listedEntities
更改为ArrayList<Entity>
而不是ArrayList<? extends Entity>
。看起来您没有特别的理由使用通配符,并且通配符禁止您添加到列表中。
将您的构造更改为:
Class<?> clazz = Class.forName(this.entityClass);
Entity newEntity = (Entity) clazz.newInstance();
listedEntities.add(newEntity);
这将解决编译错误,并且它的类型安全,因为如果this.entityClass
不是Entity
的某个子类型,显式转换会抛出异常。
我相信@RC的完全通用版本。评论中的提示将是这样的:
class Example<E extends Entity> {
private List<E> listedEntities = new ArrayList<>();
private Class<E> entityClass;
Example(Class<E> entityClass) {
this.entityClass = entityClass;
}
void method()
throws IllegalAccessException, InstantiationException {
E newEntity = entityClass.newInstance();
listedEntities.add(newEntity);
}
}
这是更恰当的&#39 ;;但是,您是否可以使用类似的东西取决于您的具体需求。
作为旁注,您的错误被抛出作为异常的事实让我有点担心。您应该使用一个正确的IDE,它会在编辑器中标记编译错误,因此您不必运行程序来查找它们。