java.lang.Class泛型和通配符

Tav*_*nes 6 java generics bounded-wildcard

为什么以下代码无法编译?

interface Iface<T> { }

class Impl<T> implements Iface<T> { }

class TestCase {
    static Class<? extends Iface<?>> clazz = Impl.class;
}
Run Code Online (Sandbox Code Playgroud)

错误是

java:不兼容的类型:java.lang.Class<Impl>无法转换为java.lang.Class<? extends Iface<?>>

但我不明白为什么通配符不能捕获.

Rad*_*def 3

这里的子类型关系是:

\n\n
          Class<? extends Iface>\n           \xe2\x95\xb1                  \xe2\x95\xb2\nClass<? extends Iface<?>>   Class<Impl>\n
Run Code Online (Sandbox Code Playgroud)\n\n

(我在对“无法从List<List>到转换List<List<?>>的回答中对此进行了解释。)

\n\n

所以本质上它不会编译,因为它是横向转换。

\n\n

如果可能的话,你可以进行我在那里描述的转换:

\n\n
(Class<? extends Iface<?>>)(Class<? extends Impl>)Impl.class\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您无法进行强制转换,那么您可能只需要处理原始有界Class<? extends Iface>. 这很烦人,主要是因为警告,但它也有可能出现错误:

\n\n
interface Iface<T> {\n    void accept(T a);\n}\n\nclass Impl2 implements Iface<String> {\n    public void accept(String a) { }\n}\n\nclass TestCase {\n    static Class<? extends Iface> clazz = Impl2.class;\n\n    public static void main(String[] args) throws Exception {\n        // throws ClassCastException\n        clazz.newInstance().accept(new Object());\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

不太可能发生,但这取决于你在做什么,我想。

\n\n
\n\n

我倾向于认为这是 Java 类型系统的问题。

\n\n
    \n
  • 可能应该有一个特殊的规则,即类型参数? extends T<?>包含类型参数? extends T,例如 aClass<? extends T>转换为 a Class<? extends T<?>>T从现有的子类型定义方式(是 的超类型)的角度来看,这是没有意义的,T<?>但从类型安全的角度来看,这是有意义的。

  • \n
  • 或者例如List.class应该是 aClass<List<?>>而不是 a Class<List>

  • \n
  • 或者比我聪明的人也能想到其他一些聪明的事情。

  • \n
\n\n

我上面描述的有趣的事情ClassCastException是它完全是人为的。事实上,通过未经检查的强制转换来阻止它会导致警告。

\n\n

我猜这只是 Java 中的泛型尚未完成的一个迹象。

\n