[英]Incompatible Generic Types: Cannot specify sub-type when using .class with generic type
There are many threads relating to Java Generics, and I'm having trouble sorting out why exactly Java doesn't support this (or alternatively, what I need to do to make it work). 有很多与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
}
}
I can fix the compile error two ways, but both of them end up dropping some kind of typing information that I want to keep! 我可以通过两种方式修复编译错误,但是它们最终都会丢弃我想保留的某种类型的输入信息!
Drop the generic Qwerty
in Thingy<Qwerty>
. 在
Thingy<Qwerty>
删除通用Qwerty
。
public class Thingy implements Thinger<String> {
..
// Ends up fixing the compile error in Thingx
Drop the generic String
in Class<? extends Thinger<String>>
删除
Class<? extends Thinger<String>>
的泛型String
Class<? extends Thinger<String>>
public class Thingx implements Thinger<String> {
@Override
public Class<? extends Thinger> getThingers() {
return Thingy.class; // Fixed!
Thingy.class
returns a Class<Thingy>
where Thingy
is a raw type since it doesn't specify a value for Qwerty
. Thingy.class
返回一个Class<Thingy>
,其中Thingy
是一个原始类型,因为它没有为Qwerty
指定值。 Since, it's a raw type, the compiler is only aware of Thingy
implementing Thinger
, instead of Thinger<String>
, since that information is lost due to type erasure. 因为,它是一个原始类型,编译器只知道
Thingy
实现Thinger
而不是Thinger<String>
,因为该信息因类型擦除而丢失。
To fix it, you can convert the Class<Thingy>
to a Class<? extends Thinger>
要解决此问题,您可以将
Class<Thingy>
转换为Class<? extends Thinger>
Class<? extends Thinger>
using Class#asSubclass
, and then the compiler allows the implicit cast to Thinger<String>
. 使用
Class#asSubclass
Class<? extends Thinger>
,然后编译器允许隐式转换为Thinger<String>
。
return Thingy.class.asSubclass(Thinger.class);
This produces no compiler or runtime errors when tested: 测试时不会产生编译器或运行时错误:
Class<? extends Thinger<String>> c = new Thingx().getThingers();
System.out.println(c.getGenericInterfaces()[0]);
Output is: 输出是:
Thinger<java.lang.String>
I'm having trouble sorting out why exactly Java doesn't support this
我无法解决为什么Java不支持这一点
Thingy.class
has type Class<Thingy>
, which is not a subtype of Class<? extends Thinger<String>>
Thingy.class
类型为Class<Thingy>
,它不是Class<? extends Thinger<String>>
的子类型Class<? extends Thinger<String>>
Class<? extends Thinger<String>>
, because Thingy
is not a subtype of Thinger<String>
. Class<? extends Thinger<String>>
,因为Thingy
不是Thinger<String>
的子类型。
Note that since Thingy
is a generic class (it is declared with a type parameter), using Thingy
by itself without a type argument is a raw type . 请注意,由于
Thingy
是一个泛型类(它使用类型参数声明),因此使用Thingy
本身而不使用类型参数是原始类型 。 When you use a raw type, you disable all generics, so the supertype of Thingy
(the raw type) is Thinger
(the raw type), not Thinger<String>
(even though Qwerty
is not involved in the relationship). 当你使用原始类型时,你禁用所有泛型,所以
Thingy
(原始类型)的超类型是Thinger
(原始类型),而不是Thinger<String>
(即使Qwerty
没有参与关系)。 This is similar to how if you call a method on a raw type like Thingy
, all generics are turned off in the parameter and return types of the method, even if they have nothing to do with Qwerty
. 这类似于如果在像
Thingy
这样的原始类型上调用方法,所有泛型都在参数和方法的返回类型中关闭,即使它们与Qwerty
无关。 This is just one of the reasons to avoid raw types. 这只是避免原始类型的原因之一。
It works for Thingx.class
because Thingx
is a subtype of Thinger<String>
, as Thingx
is not a raw type because the class Thingx
is not generic. 它适用于
Thingx.class
因为Thingx
是 Thinger<String>
的子类型,因为Thingx
不是原始类型,因为类Thingx
不是通用的。
As others have noted, there doesn't seem to be any reason why Thingy
is generic, as the type parameter Qwerty
is never used inside Thingy
. 正如其他人所指出的那样,似乎没有任何理由为什么
Thingy
是通用的,因为类型参数Qwerty
从未在Thingy
使用Thingy
。 So the best choice would be to remove it. 因此,最好的选择是删除它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.