[英]Java: Nested recursive generics
我有一组扩展一些基本实体的类。 此集合中的类也可以相互扩展,从而创建嵌套层次结构。
我的目标是让所有类都可以访问创建自己的新实例的方法 。 我想在我的基本实体中实现此方法,以便所有扩展类继承此方法。
以下是为我的模式定义的三个示例类:
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方法中的编译器错误。 我做错了什么,如何解决这个问题?
请注意,这是一个人为的例子,涉及我正在努力解决的更大问题。 我知道这个实现本身看起来很傻。
Collection<E...>
是泛型类型,但Collection c
是原始类型。 这意味着它的所有方法都将被视为原始类型,这意味着它们将返回任何泛型的擦除。
您的基类声明为BaseEntity<E extends BaseEntity>
,这意味着在此方法中:
E getNewInstance()
擦除是
BaseEntity getNewInstance();
这意味着c.getNewInstance()
返回一个BaseEntity
,而不是一个Collection
,这是编译错误的来源。
另一方面, Document
不是通用类。 这意味着擦除在编译时无关紧要(出于这些目的),并且getNewInstance()
返回E
表示的类型,在本例中为Document
。 因此, d.getNewInstance()
的返回类型为Document
,因此该行编译正常。
顺便说一句:每当你有递归泛型时,你应该确保在递归中考虑泛型。 例如,在这一行:
BaseEntity<E extends BaseEntity>
您已将BaseEntity
定义为泛型类 - 但随后在E extends BaseEntity
立即忽略其泛型。 那条线应该是:
BaseEntity<E extends BaseEntity<E>>
这个构造函数的问题
public Collection() {
super(Collection.class);
}
是超类构造函数是否期望Class<E>
,但类文本Collection.class
是Class<Collection>
。 这些类型是不兼容的,因为E
可以是Collection
, Document
或可能扩展Collection
任何其他类型。
像Document
这样扩展Collection
的类必须提供自己的类,所以它将调用另一个接受Class<E>
Collection
构造函数,所以我不认为Collection()
构造函数有任何用处。 我会删除它。
此外,在E
的上限中,您使用的是您尝试制作泛型的类的原始形式。 采用
public abstract class BaseEntity<E extends BaseEntity<E>> {
和
public class Collection<E extends Collection<E>> extends BaseEntity<E> {
类型Collection
是通用的,因此您必须指定与Collection
构造函数的参数匹配的泛型类型参数。
Collection<Document> c = new Collection<Document>(Document.class);
c = c.getNewInstance();
文档本身不是通用的,所以这段代码仍然很好:
Document d = new Document();
d = d.getNewInstance();
即使直接创建Document
, Document
必须作为Collection
的类型参数提供,因为Document
是Collection<Document>
。
Collection<Document> cd = new Document();
cd = cd.getNewInstance();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.