简体   繁体   English

Java泛型编译错误涉及Class <?延伸T>

[英]Java generics compile error involving Class<? extends T>

This program does not compile: 这个程序不编译:

public class xx {
    static class Class1<C> {
        void method1(C p) {
        }
    }
    static class Class2<T> extends Class1<Class<? extends T>> {
        T object;
        void method2() {
            this.method1(this.object.getClass());
        }
    }
}

The error is: 错误是:

xx.java:10: method1(java.lang.Class<? extends T>) in xx.Class1<java.lang.Class<? extends T>>
cannot be applied to (java.lang.Class<capture#215 of ? extends java.lang.Object>)
        this.method1(this.object.getClass());

Why does this happen? 为什么会这样? Why does the compiler seemingly believe that object.getClass() returns Class<? extends Object> 为什么编译器似乎相信object.getClass()返回Class<? extends Object> Class<? extends Object> instead of Class<? extends T> Class<? extends Object>而不是Class<? extends T> Class<? extends T> ? Class<? extends T>

There is no upper bound set on T in your code, so ? extends T 您的代码中的T上没有上限设置,所以? extends T ? extends T is really tantamount to ? extends Object ? extends T真的无异于? extends Object ? extends Object . ? extends Object Just yesterday I played with a similar example and hit this barrier. 就在昨天,我玩了一个类似的例子,并打了这个障碍。 I had 我有

static <T> T newInstance(T o) throws Exception {
  final Class<? extends T> c = o.getClass();
  return c.newInstance();
}

and it complained with the same error. 它抱怨同样的错误。 Consider this: the return type of Object.getClass() is Class<?> and the compiler will want to capture the ? 考虑一下: Object.getClass()的返回类型是Class<?> ,编译器想要捕获? into a concrete type. 成为具体类型。 But instead, we would like not to capture the ? 但相反,我们不想捕获? , but to "capture the upper bound" T -- and there is no such thing in Java's generics. ,但要“捕获上限” T - 并且在Java的泛型中没有这样的东西。

Object.getClass() is defined to return a Class<? extends |T|> Object.getClass()被定义为返回一个Class<? extends |T|> Class<? extends |T|> , where T is the statically known type of the receiver (the object getClass() is called on). Class<? extends |T|> ,其中T是静态已知类型的接收器(调用对象getClass() )。 Take special note of the vertical bars, the erasure operator . 特别注意垂直条, 擦除操作符 The erasure of a type variable is the erasure of its leftmost bound. 类型变量的擦除是其最左边界的擦除。 In your case that's the implicit bound Object . 在你的情况下,这是隐式绑定Object So you get back a Class<? extends Object> 所以你得到一个Class<? extends Object> Class<? extends Object> , not a Class<? extends T> Class<? extends Object> ,而不是Class<? extends T> Class<? extends T> . Class<? extends T>

Why is that? 这是为什么?

Imagine T = List<Integer> , you could suddenly do the following without unchecked warning : 想象一下T = List<Integer> ,如果没有未经检查的警告 ,您可以突然执行以下操作:

List<String> myStrings = new ArrayList<>();
List<Integer> myInts = new ArrayList<>();
List<Integer> myIntyStrings = myInts.getClass().cast(myStrings);
myIntyStrings.add(-1);
String myString = myStrings.get(0); // BANG!

But thankfully we do get a warning.. ;) 但幸运的是,我们确实收到警告..;)

According to the documentation on getClass(), the returned object has type Class< ? extends |X| > 根据getClass()的文档,返回的对象的类型为Class< ? extends |X| > Class< ? extends |X| > Class< ? extends |X| > , where |X| Class< ? extends |X| > ,其中|X| is the erasure of the type of the instance on which the method is called. 是调用该方法的实例类型的擦除。

Therefore calling getClass() on an object of type T returns Class< ? extends Object > 因此,在类型为T的对象上调用getClass()会返回Class< ? extends Object > Class< ? extends Object > . Class< ? extends Object > We have no bound information about T in this API. 我们在此API中没有关于T绑定信息。

Usually APIs which use reflection on generic classes require that the client pass an additional argument of type Class< T > to the constructor or generic method in question. 通常,在泛型类上使用反射的API要求客户端将类型为Class< T >的附加参数传递给相关的构造函数或泛型方法。

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

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