Java:嵌套递归泛型
我有一组扩展一些基本实体的类。该集中的类也可以相互扩展,从而创建嵌套的层次结构 我的目标是让所有类都能访问一个方法,该方法可以创建它们自己的新实例。我想在我的基本实体中实现这个方法,以便所有扩展类都继承这个方法 下面是为我的模式定义的三个示例类: BaseEntity.javaJava:嵌套递归泛型,java,generics,Java,Generics,我有一组扩展一些基本实体的类。该集中的类也可以相互扩展,从而创建嵌套的层次结构 我的目标是让所有类都能访问一个方法,该方法可以创建它们自己的新实例。我想在我的基本实体中实现这个方法,以便所有扩展类都继承这个方法 下面是为我的模式定义的三个示例类: BaseEntity.java public abstract class BaseEntity<E extends BaseEntity> { Class<E> clazz; public BaseEnti
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();
}
}
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);
}
}
public class Document extends Collection<Document> {
public Document() {
super(Document.class);
}
}
但是请注意,Collection.java
的默认构造函数中存在编译器错误。我不确定这是为什么造成的,我认为这也是导致示例main方法中的编译器错误的原因。我做错了什么,如何解决
请注意,这是一个人为的例子,与我试图解决的一个更大的问题有关。我知道这个实现本身看起来很傻。集合
是泛型类型,但您的集合c
是原始类型。这意味着它的所有方法都将被视为原始类型,这意味着它们将返回对其中任何泛型的擦除
您的基类被声明为BaseEntity
,这意味着在此方法中:
E getNewInstance()
删除是错误的
BaseEntity getNewInstance();
这意味着c.getNewInstance()
返回一个BaseEntity
,而不是一个集合,这就是编译错误的原因
另一方面,文档
不是泛型类。这意味着在编译时擦除并不重要(出于这些目的),getNewInstance()
返回E
表示的类型,在本例中为Document
。同样地,d.getNewInstance()
的返回类型为Document
,因此该行可以很好地编译
顺便说一句:只要有递归泛型,就应该确保在递归中考虑泛型。例如,在这一行中:
BaseEntity<E extends BaseEntity>
这个构造函数的问题
public Collection() {
super(Collection.class);
}
超类构造函数需要一个类
,但类literal集合。类
是一个类
。这些类型是不兼容的,因为E
可能是集合
,文档
,或者可能扩展集合
的任何其他类型
任何像Document
这样扩展Collection
的类都必须提供自己的类,因此它将调用另一个Collection
构造函数,该构造函数接受类,因此我认为Collection()
构造函数没有任何用处。我会移除它
另外,在E
的上限中,您使用的正是试图使泛型的类的原始形式。使用
public abstract class BaseEntity<E extends BaseEntity<E>> {
文档本身不是泛型的,因此此代码仍然可以:
Document d = new Document();
d = d.getNewInstance();
文档
必须作为类型参数提供给集合
,即使直接创建文档
,因为文档
是集合
Collection cd=新文档();
cd=cd.getNewInstance();
与两个流行的java库类的名称冲突会导致混淆……完全有道理,解释得很好。我认为我的问题的一部分是我很难理解递归泛型BaseEntity
是我很难理解的一个例子。但是我需要花更多的时间来理解,再次感谢。你能解释一下BaseEntity
和BaseEntity之间的区别吗?这比一个注释要大一点——这可能值得一个后续问题(我没有发现任何关于“带通配符的java递归泛型”的内容)。但是基本上不同之处在于泛型类本身在E
上使用方法。考虑是否有一个方法,使用了<代码> e实体< />代码,并称为<代码>实体.GETNEVEN()/<代码>。使用extensedbaseentity
,您将得到E
。使用extensedbaseentity
,您将返回一个BaseEntity
。在这里,只需BaseEntity
就没有必要执行BaseEntity
。我理解主要方法中的差异。我仍然存在的一个问题是,即使在更改了类头之后,我的集合
默认构造函数中仍然存在相同的编译器错误。我认为集合
的默认构造函数是无用的。我建议删除它。当您必须寻找一个具体的子类时,集合
有什么好处?此外,这将迫使您编写Collection
,这将迫使Collection
,以及无限多级别的泛型。
public abstract class BaseEntity<E extends BaseEntity<E>> {
public class Collection<E extends Collection<E>> extends BaseEntity<E> {
Collection<Document> c = new Collection<Document>(Document.class);
c = c.getNewInstance();
Document d = new Document();
d = d.getNewInstance();
Collection<Document> cd = new Document();
cd = cd.getNewInstance();