使用反射

时间:2017-01-15 20:48:22

标签: java arraylist reflection

所以我有一个未知类型的对象的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 ?)

1 个答案:

答案 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,它会在编辑器中标记编译错误,因此您不必运行程序来查找它们。