3

我遇到了泛型问题,我认为是类型擦除,同时试图反映一些通用信息。

我正在使用基于http://www.artima.com/weblogs/viewpost.jsp?thread=208860的类来进行反射,但这不是问题。

下面的代码演示了这个问题:

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;
        }
    }
}

不幸的是这条线

classIWant = c.asSubclass(MyClass1.class);

显示以下错误

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

这真的让我很困惑。U 扩展 MyClass1,因此 U 是 MyClass1。

显然,这里有一些我不理解的类型擦除 - 任何人都可以帮忙,拜托。顺便说一句,这是 Java 1.7.0_40

谢谢

康拉德温彻斯特

4

2 回答 2

1

该方法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());
}

返回类型为Class<? extends U>. 请注意,方法中的 yourU和 theUasSubclass完全不相关的类型变量。

因此,该方法asSubclass()返回一个声明为Class的某个未知子类型的值UU在本例中为MyClass1

您正在尝试将此值分配给Class具有某些已知子类型的类型变量MyClass1。编译器不能保证它们匹配,因此不允许编译。

ClassCastException如果您愿意,您可以转换返回的值,但如果类型不匹配,则可能最终会在运行时获得。

于 2013-11-04T17:12:22.640 回答
1

Java 编译器无法保证Class对象c与泛型类型匹配U。由于类型擦除,由编译器来保证类型安全,并确保Classc.asSubclass匹配返回Class<U>,但它不能。

asSubclass方法返回一个Class<? extends U>. 在Class类中,U表示Class传入的类型asSubclass。当你调用它时,就是c. 但是编译器不能保证这个返回类型与你自己声明的相匹配<U extends MyClass1>。它们可能是不同的子类MyClass1

如果可以保证c.asSubclass将返回 a Class<U>,则将其转换为 a Class<U>

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

您将收到“未经检查的演员表”警告。这是因为编译器不能保证 is 真的是 a Class<U>,但你说它是。请小心,因为这可能会导致在其他地方难以追踪ClassCastException,即使在您返回U. 仅当您可以自己保证类型安全时才这样做。

于 2013-11-04T17:12:51.043 回答