我正在尝试在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
的组件?
答案 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;
}
此解决方案可以正确编译和运行。