Java:嵌套递归泛型

use*_*880 7 java 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();
    }

}
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方法中的编译器错误.我做错了什么,如何解决这个问题?

请注意,这是一个人为的例子,涉及我正在努力解决的更大问题.我知道这个实现本身看起来很傻.

ysh*_*vit 8

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)