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