不兼容的通用类型:使用带有泛型类型的.class时,无法指定子类型

时间:2016-08-27 03:56:54

标签: java generics types

有很多与Java Generics相关的线程,我在解决Java为什么不支持这个问题时遇到了麻烦(或者我需要做些什么才能使它工作)。

public interface Thinger<T> {

    Class<? extends Thinger<T>> getThingers();
}

public class Thingy<Qwerty> implements Thinger<String> {

    @Override
    public Class<? extends Thinger<String>> getThingers() {
        return Thingx.class;
    }
}

public class Thingx implements Thinger<String> {

    @Override
    public Class<? extends Thinger<String>> getThingers() {
        return Thingy.class;    // Incompatible types error
    }
}

我可以通过两种方式解决编译错误,但是它们最终都会丢弃我想保留的某种类型的输入信息!

选项1

将通用Qwerty放入Thingy<Qwerty>

public class Thingy implements Thinger<String> {
    ..
// Ends up fixing the compile error in Thingx

选项2

删除String

中的通用Class<? extends Thinger<String>>
public class Thingx implements Thinger<String> {

    @Override
    public Class<? extends Thinger> getThingers() {
        return Thingy.class;    // Fixed!

2 个答案:

答案 0 :(得分:0)

Thingy.class返回Class<Thingy>,其中Thingy是原始类型,因为它没有为Qwerty指定值。由于它是原始类型,因此编译器只知道Thingy实现Thinger而不是Thinger<String>,因为该信息因类型擦除而丢失。

要解决此问题,您可以使用Class#asSubclassClass<Thingy>转换为Class<? extends Thinger>,然后编译器允许隐式转换为Thinger<String>

return Thingy.class.asSubclass(Thinger.class);

测试时不会产生编译器或运行时错误:

Class<? extends Thinger<String>> c = new Thingx().getThingers();
System.out.println(c.getGenericInterfaces()[0]);

输出是:

Thinger<java.lang.String>

答案 1 :(得分:0)

  

我无法理清为什么Java不支持这个

Thingy.class的{​​{1}}类型不是Class<Thingy>的子类型,因为Class<? extends Thinger<String>>不是Thingy的子类型。

请注意,由于Thinger<String>是泛型类(使用类型参数声明),因此在没有类型参数的情况下单独使用Thingy原始类型。当您使用原始类型时,禁用所有泛型,因此Thingy(原始类型)的超类型为Thingy(原始类型),而不是Thinger(即使{{1}不参与关系)。这类似于如果在Thinger<String>之类的原始类型上调用方法,所有泛型都在参数中关闭并返回方法的类型,即使它们与Qwerty无关。这只是避免原始类型的原因之一。

适用于Thingy,因为Qwerty Thingx.class的子类型,因为Thingx不是原始类型,因为类{{ 1}}不是通用的。

正如其他人所指出的那样,Thinger<String>通用似乎没有任何理由,因为类型参数Thingx从未在Thingx中使用。所以最好的选择就是删除它。