繁体   English   中英

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是原始类型。 这意味着它的所有方法都将被视为原始类型,这意味着它们将返回任何泛型的擦除。

您的基类声明为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.classClass<Collection> 这些类型是不兼容的,因为E可以是CollectionDocument或可能扩展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();

即使直接创建DocumentDocument必须作为Collection的类型参数提供,因为DocumentCollection<Document>

Collection<Document> cd = new Document();
cd = cd.getNewInstance();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM