繁体   English   中英

Java泛型类型问题

[英]Java generic type issue

考虑以下简化示例:

package com.test;

class B<S> {
    B(Class<S> clazz) {}
}

class A<T> {
    class SubB extends B<SubB> {
        SubB() {
            super(SubB.class);
        }
    }
}

尽管 IntelliJ 没有显示任何错误(就像存在编译错误时通常那样),但启动程序时的实际编译以位于super(SubB.class);错误结束super(SubB.class);

错误:(8, 23) java:不兼容的类型: java.lang.Class<com.test.A.SubB>无法转换为java.lang.Class<com.test.A<T>.SubB>

我很好奇,为什么会这样? 我怎么能解决呢?

编译是使用 AdoptOpenJDK 11 完成的。

这种行为的原因有点复杂。 考虑java.util.List.class ,它的类型为Class<java.util.List> ,而不是Class<java.util.List<?>> 这是类文字的限制。

在您的示例中, SubB.class的类型为Class<com.test.A.SubB> ,同样具有 SubB 的原始类型。 但是构造函数需要某种类型的Class<com.test.A<T>.SubB>

这就是为什么我们需要将文字转换为所需的类型:

super((Class<SubB>) (Class<?>) SubB.class);

这将产生警告,但快速检查将表明没有什么可担心的。

我觉得这很有趣。

这里的问题是,当你声明这个时:

class A<T> {

    class SubB extends B<SubB> {
        SubB() {
            super...
        }
    }
}

B<SubB>实际上是B<A<T>.SubB> (我什至不知道这是可能的)。 这很容易为javap证明 thx(只需反编译该类并亲自查看)。 一旦你把它写成“长”形式:

class A<T> {
    class SubB extends B<A<T>.SubB> {
        SubB() {
            super(....);
        }
    }
}

它开始变得更有意义。

理想情况下,要使其正常工作,您必须能够编写:

super(A<T>.SubB.class);

但是 java 不允许这样做, .class只能在原始类型上调用。

最好的方法是在这里明确:

class A<T> {
    class SubB extends B<A.SubB> {
        SubB() {
            super(SubB.class);
        }
    }
}

在说:我正在使用A的原始类型: B<A.SubB>

在泛型中,继承并不像我们通常所知道的那样,即让我们举个例子类ArrayList<String>不是List的子类。 List<String>List

同样在泛型中,您通常不会轻易得到编译错误,因为在编译期间泛型类型被转换为它们的原始类型。

因此,我们需要按照@JohannesKuhn 所述进行转换。

暂无
暂无

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

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