Java:嵌套递归泛型
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
是原始类型。这意味着 所有 它的方法将被视为原始类型,这意味着它们将 return 擦除那里的任何泛型。
你的基础class被声明为BaseEntity<E extends BaseEntity>
,这意味着在这个方法中:
E getNewInstance()
擦除是
BaseEntity getNewInstance();
这意味着 c.getNewInstance()
return 是 BaseEntity
,而不是 Collection
,这就是您的编译错误所在。
另一方面,Document
不是 通用 class。这意味着擦除在编译时并不重要(出于这些目的),并且 getNewInstance()
returns E
表示的类型,在这种情况下是 Document
.因此,d.getNewInstance()
的 return 类型为 Document
,因此该行可以正常编译。
顺便说一句:每当你有递归泛型时,你应该确保在递归中考虑泛型。例如,在这一行中:
BaseEntity<E extends BaseEntity>
您已将 BaseEntity
定义为泛型 class -- 但随后立即忽略了 E extends BaseEntity
中的泛型。该行应该改为:
BaseEntity<E extends BaseEntity<E>>
这个构造函数的问题
public Collection() {
super(Collection.class);
}
是 superclass 构造函数期望 Class<E>
,但 class 文字 Collection.class
是 Class<Collection>
。这些类型不兼容,因为 E
可能是 Collection
、Document
或任何其他可能扩展 Collection
.
的类型
任何像 Document
这样扩展 Collection
的 class 必须提供自己的 class,因此它将调用另一个 Collection
构造函数Class<E>
无论如何,所以我认为 Collection()
构造函数没有任何用处。我会删除它。
此外,在 E
的上限中,您使用的是您正试图使其通用的 classes 的原始形式。使用
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();
我有一组 类 扩展了一些基本实体。 类 此集合中的也可以相互扩展,创建嵌套层次结构。
我的目标是让 所有 类 都可以访问创建自己新实例的方法 。我想在我的基本实体中实现这个方法,以便所有扩展 类 继承这个。
这里是为我的模式定义的三个示例 类:
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
是原始类型。这意味着 所有 它的方法将被视为原始类型,这意味着它们将 return 擦除那里的任何泛型。
你的基础class被声明为BaseEntity<E extends BaseEntity>
,这意味着在这个方法中:
E getNewInstance()
擦除是
BaseEntity getNewInstance();
这意味着 c.getNewInstance()
return 是 BaseEntity
,而不是 Collection
,这就是您的编译错误所在。
Document
不是 通用 class。这意味着擦除在编译时并不重要(出于这些目的),并且 getNewInstance()
returns E
表示的类型,在这种情况下是 Document
.因此,d.getNewInstance()
的 return 类型为 Document
,因此该行可以正常编译。
顺便说一句:每当你有递归泛型时,你应该确保在递归中考虑泛型。例如,在这一行中:
BaseEntity<E extends BaseEntity>
您已将 BaseEntity
定义为泛型 class -- 但随后立即忽略了 E extends BaseEntity
中的泛型。该行应该改为:
BaseEntity<E extends BaseEntity<E>>
这个构造函数的问题
public Collection() {
super(Collection.class);
}
是 superclass 构造函数期望 Class<E>
,但 class 文字 Collection.class
是 Class<Collection>
。这些类型不兼容,因为 E
可能是 Collection
、Document
或任何其他可能扩展 Collection
.
任何像 Document
这样扩展 Collection
的 class 必须提供自己的 class,因此它将调用另一个 Collection
构造函数Class<E>
无论如何,所以我认为 Collection()
构造函数没有任何用处。我会删除它。
此外,在 E
的上限中,您使用的是您正试图使其通用的 classes 的原始形式。使用
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();