Java实体组件系统 - 推理变量T具有不兼容的边界

时间:2018-02-15 01:53:04

标签: java components entity system

我正在尝试在java中创建一个自定义实体组件系统,我在类型擦除方面遇到了一些困难。整个系统正常运行保存一种方法。我希望能够调用泛型方法createEntity(Class<? extends Component>... types);,它接收var args数组类型,创建一个新的空白实体,并使用反射添加指定类型的新组件。这是我写的方法。

public Entity createEntity(Class<? extends Component>... types){
    Entity e = new Entity();  
    for(Class<? extends Component> type: types){
        try {
            getParent().getComponentManager().add(type, e.UID, type.newInstance());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }              
    INDEX.add(e.UID, e);
    return e;
}  

这是创建编译错误的行。

getParent().getComponentManager().add(type, e.UID, type.newInstance());

这是ComponentManager类内部的方法。

public <T extends Component> void add(Class<T> type, int uid, T component){
    if(component != null){
        ComponentIndex<T> index = getComponentsByType(type);
        if(!index.has(uid)){
            index.add(uid, component);
            component.setParent(this);
        }
    }        
}

Component类只是一个空接口。

public interface Component{}

我从NetBeans工具提示中得到的错误与

类似
  

...类ComponentManager中的方法add不能应用于给定的类型;    required:Class,int,T    发现:Class,int,Class    原因:推理变量T具有不兼容的界限......

如果所有组件都将实现Class<?>接口,并且所有组件都有一个没有参数的构造函数,我如何使用反射来创建基于泛型Component的组件?

1 个答案:

答案 0 :(得分:0)

因此,在阅读本文后,我找到了解决此特定问题的方法。 https://docs.oracle.com/javase/tutorial/java/generics/capture.html

问题在于,使用通配符时,编译器无法保证对象的类型正确,但通过使用通用帮助器方法,您可以通过捕获通配符的类型来确保每个元素的类型安全性。在这种情况下,这是我使用的辅助方法。

private <T extends Component> void addNewComponentInstance(Class<T> type, int uid){
    try {
        getParent().getComponentManager().add(type, uid, type.newInstance());
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

这就是它被夹在通配符方法中的方式。

public Entity createEntity(Class<? extends Component>... types){
    Entity e = new Entity();  
    for(Class<? extends Component> type: types)
        addNewComponentInstance(type, e.UID);                   
    INDEX.add(e.UID, e);
    return e;
}

此解决方案可以正确编译和运行。