我有一组扩展一些基本实体的类.此集合中的类也可以相互扩展,从而创建嵌套层次结构.
我的目标是让所有类都可以访问创建自己的新实例的方法.我想在我的基本实体中实现此方法,以便所有扩展类继承此方法.
以下是为我的模式定义的三个示例类:
BaseEntity.java
public abstract class BaseEntity<E extends BaseEntity> { Class<E> clazz; public BaseEntity(Class<E> clazz) { this.clazz = clazz; } public E getNewInstance() throws IllegalAccessException,InstantiationException { return clazz.newInstance(); } }
Collection.java
public class Collection<E extends Collection> extends BaseEntity<E> { public Collection() { super(Collection.class); // compiler error: BaseEntity (java.lang.Class<E>) in BaseEntity cannot be applied to // (java.lang.Class<Collection>) } public Collection(Class<E> clazz) { super(clazz); } }
Document.java
public class Document extends Collection<Document> { public Document() { super(Document.class); } }
有了这个设置,我希望能够做到这样的事情:
Collection c = new Collection(); c = c.getNewInstance(); // compiler error Document d = new Document(); d = d.getNewInstance(); Collection cd = new Document(); cd = cd.getNewInstance(); // compiler error
但请注意,Collection.java的默认构造函数中存在编译器错误.我不确定为什么会造成这种情况,我认为这也会导致示例main方法中的编译器错误.我做错了什么,如何解决这个问题?
请注意,这是一个人为的例子,涉及我正在努力解决的更大问题.我知道这个实现本身看起来很傻.
解决方法
收集和LT,E …>是一种泛型类型,但您的Collection c是原始类型.这意味着它的所有方法都将被视为原始类型,这意味着它们将返回任何泛型的擦除.
您的基类声明为BaseEntity< E extends BaseEntity>,这意味着在此方法中:
E getNewInstance()
擦除是
BaseEntity getNewInstance();
这意味着c.getNewInstance()返回一个BaseEntity,而不是一个Collection,这是编译错误的来源.
另一方面,文档不是通用类.这意味着擦除在编译时无关紧要(出于这些目的),并且getNewInstance()返回E表示的类型,在本例中为Document.因此,d.getNewInstance()的返回类型为Document,因此该行编译正常.
顺便说一句:每当你有递归泛型时,你应该确保在递归中考虑泛型.例如,在这一行:
BaseEntity<E extends BaseEntity>
您已将BaseEntity定义为泛型类 – 但随后立即忽略其在E扩展BaseEntity中的泛型.那条线应该是:
BaseEntity<E extends BaseEntity<E>>