简体   繁体   English

Java泛型:为什么someObject.getClass()不返回Class <? extends T> ?

[英]Java generics: why someObject.getClass() doesn't return Class<? extends T>?

I would expect that from the aspect of compile time as well as from the aspect of runtime it wouldn't be a problem for .getClass() to provide a correctly-typed return value. 我希望从编译时以及运行时的角度来看, .getClass()提供正确类型的返回值都不会成为问题。

But I must be wrong. 但是我一定是错的。

public class _GetClassGenerics2 {

  static class MyClass {
  }

  public static void main(String[] args) {
    MyClass myInstance = new MyClass();
    // here it works
    Class<? extends MyClass> type = myInstance.getClass();

    myMethod(myInstance);
  }

  public static <T extends MyClass> void myMethod(T instance) {
    Class<? extends T> type = instance.getClass();
// java.lang.RuntimeException: Uncompilable source code - incompatible types
//  required: java.lang.Class<? extends T>
//  found:    java.lang.Class<capture#1 of ? extends _GetClassGenerics2.MyClass>
  }

}

EDIT: It doesn't work with Class<T> and Class<? super T> 编辑:它不适用于Class<T>Class<? super T> Class<? super T> either. Class<? super T>

java.lang.Class does not represent a type (use java.lang.reflect.Type for that). java.lang.Class不代表类型(为此使用java.lang.reflect.Type )。 If T , were say ArrayList<String> then it makes no sense for there to be a Class<ArrayList<String>> . 如果TArrayList<String>则没有Class<ArrayList<String>>

It's worth noting that in this particular case there is no need for the method to be generic. 值得注意的是,在这种特殊情况下,不需要通用方法。

public static <T extends MyClass> void myMethod(T instance) {

Is equivalent to: 等效于:

public static void myMethod(MyClass instance) {

As per the Javadoc of the getClass method : 按照getClass方法的Javadoc

The actual result type is Class<? extends |X|> 实际的结果类型是Class<? extends |X|> Class<? extends |X|> where |X| Class<? extends |X|>其中| X | is the erasure of the static type of the expression on which getClass is called. 是擦除在其上调用getClass的表达式的静态类型。 For example, no cast is required in this code fragment 例如,此代码段中不需要强制转换

Here, the value for |X| 这里, |X|的值 in your code snippet is MyClass , hence instance.getClass() is assignable to only Class<? extends MyClass> 您的代码段中是MyClass ,因此instance.getClass()只能分配给Class<? extends MyClass> Class<? extends MyClass> or Class<?> . Class<? extends MyClass>Class<?>

The reason for this specific wording is because when you say that for this variable having type T where <T extends MyClass> , there can be multiple classes which extend MyClass and hence capable of satisfying the T extends MyClass criteria. 使用这种特定措辞的原因是因为当您说该类型为T的变量(其中<T extends MyClass> ,可以存在多个扩展MyClass类,因此能够满足T extends MyClass条件。 Without runtime information there is no way of knowing which concrete implementation subclass of MyClass was passed in the method. 没有运行时信息,就无法知道在方法中传递了MyClass哪个具体实现子类。 Hence to provide a generic solution, it returns <? extends MyClass> 因此,为了提供通用解决方案,它返回<? extends MyClass> <? extends MyClass> since that would hold true for any subclass of MyClass irrespective of what class instance is passed in. <? extends MyClass>因为无论传入什么类实例,这对于MyClass任何子类都适用。

Java does not support a generic type of <this> eg Java不支持<this>的通用类型,例如

Object could implement 对象可以实现

class Object {
    Class<this> getClass()
}

But there is no way for getClass() to express that it will return a type which is the class of the object. 但是getClass()无法表示将返回一个类型,即对象的类。 The compiler has no native understand of what this method does either. 编译器也不了解此方法的功能。

IMHO, This behaviour should have been supported. 恕我直言,此行为应得到支持。

Instead of 代替

Class<? extends T> type = instance.getClass();

you need to use 你需要使用

Class<? extends MyClass> type = instance.getClass();

You cannot directly use the T here. 您不能在此处直接使用T

The reason is the method signature of Object.getClass() (which you are invoking). 原因是Object.getClass()的方法签名(正在调用)。 It's: 它的:

public final Class<? extends Object> getClass()

So you are trying to convert from Class<? extends Object> 因此,您正在尝试从Class<? extends Object>转换Class<? extends Object> Class<? extends Object> to Class<? extends T> Class<? extends Object>Class<? extends T> Class<? extends T> , which is not allowed (because you are down-casting). Class<? extends T> ,这是不允许的(因为您正在向下广播)。 It is allowed using an explicit cast: 使用一个明确允许投:

Class<? extends T> type = (Class<? extends T>) instance.getClass();

will work (though it generates a type safety warning). 将起作用(尽管它会生成类型安全警告)。

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

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