简体   繁体   English

意外类型擦除

[英]Unexpected Type Erasure

I am having an issue with generics and what I presume is type erasure whilst trying to reflect some generic information. 我有一个泛型问题,我猜想是类型擦除,同时试图反映一些通用信息。

I am using a class based on http://www.artima.com/weblogs/viewpost.jsp?thread=208860 to do the reflection, but that isn't the issue. 我正在使用基于http://www.artima.com/weblogs/viewpost.jsp?thread=208860的类进行反射,但这不是问题。

The code below demonstrates the issue: 下面的代码演示了这个问题:

private <U extends MyClass1> U doSomething(MyClass2<U> p) {
     Class<U> classIWant = null;
     for (Class<?> c : GenericTypeUtils.getTypeArguments(MyClass2.class, p.getClass()))      {
        if (MyClass1.class.isAssignableFrom(c)) {
            classIWant = c.asSubclass(MyClass1.class);
            break;
        }
    }
}

Unfortunately the line 不幸的是行

classIWant = c.asSubclass(MyClass1.class);

Shows the following error 显示以下错误

java: incompatible types
  required: java.lang.Class<U>
  found:    java.lang.Class<capture#4 of ? extends MyClass1>

And that's really confusing me. 这真让我困惑。 U extends MyClass1 and therefore U is a MyClass1. U扩展了MyClass1,因此U是MyClass1。

Obviously there is some piece of type erasure I am not understanding here - can anybody help, please. 显然有一些类型的擦除我不明白 - 请有人帮忙。 BTW this is Java 1.7.0_40 BTW这是Java 1.7.0_40

Thanks 谢谢

Conrad Winchester 康拉德温彻斯特

The method asSubclass() is implemented like so 方法asSubclass()就像这样实现

public <U> Class<? extends U> asSubclass(Class<U> clazz) {
    if (clazz.isAssignableFrom(this))
        return (Class<? extends U>) this;
    else
        throw new ClassCastException(this.toString());
}

with a return type of Class<? extends U> 返回类型为Class<? extends U> Class<? extends U> . Class<? extends U> Note, that your U and the U in the asSubclass method are completely unrelated type variables. 请注意, asSubclass方法中的UU是完全不相关的类型变量。

So the method asSubclass() returns a value declared with the type Class of some unknown subtype of U , where U in this case is MyClass1 . 因此asSubclass()方法返回一个声明的值,该类的类型为某个未知的U类型的子Class ,其中U在这种情况下是MyClass1

You are trying to assign this value to a variable of type Class with some known subtype of MyClass1 . 您正在尝试将此值分配给类型为Class的变量,并使用某些已知MyClass1子类型。 The compiler can't guarantee that they match and therefore doesn't allow compilation. 编译器无法保证它们匹配,因此不允许编译。

You can cast the returned value if you wish, but may end up getting ClassCastException at runtime, if the types don't match. 如果您愿意,可以强制转换返回的值,但如果类型不匹配,最终可能会在运行时获取ClassCastException

The Java compiler is unable to guarantee that the Class object c matches the generic type U . Java编译器无法保证Class对象c与泛型类型U匹配。 Because of type erasure, it is up to the compiler to guarantee type safety, and ensure that the Class coming back from c.asSubclass matches Class<U> , but it can't. 由于类型擦除,编译器需要保证类型安全,并确保从c.asSubclass返回的ClassClass<U>匹配,但它不能。

The asSubclass method returns a Class<? extends U> asSubclass方法返回一个Class<? extends U> Class<? extends U> . Class<? extends U> In the Class class, U represents the type of Class passed into asSubclass . Class类中, U表示传入asSubclassClass类型。 When you call it, that is c . 当你打电话给它时,那就是c But the compiler cannot guarantee that this return type matches your own declared <U extends MyClass1> . 但编译器无法保证此返回类型与您自己声明的<U extends MyClass1>匹配。 They could be different subclasses of MyClass1 . 它们可以是MyClass1不同子类。

If you can guarantee that c.asSubclass will return a Class<U> , then cast it as a Class<U> : 如果能保证c.asSubclass将返回一个Class<U>然后将它转换为Class<U>

classIWant = (Class<U>) c.asSubclass(MyClass1.class);

You will receive an "unchecked cast" warning. 您将收到“未经检查的演员”警告。 This is there because the compiler cannot guarantee that is really is a Class<U> , but you are saying that it is. 这是因为编译器不能保证它确实是一个Class<U> ,但你说的是它。 Be careful as this may result in a hard-to-track-down ClassCastException elsewhere, even after you return the U . 请注意,即使在返回U之后,这可能会导致其他地方难以跟踪ClassCastException Do this only if you can guarantee the type safety yourself. 只有在您可以自己保证类型安全的情况下才能这样做。

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

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