【问题标题】:generic type parameter泛型类型参数
【发布时间】:2011-04-05 21:15:32
【问题描述】:

我定义了以下类

public class AbstractManager<E> {

    public E save(E o) {
        // Implementation omitted
    }

    public <T> T getSingleResult(Query query, Class<T> clazz) {
        return clazz.cast(query.getSingleResult());
    }
}

public class MatchingAlgorithmManagerImpl extends AbstractManager {

    void someMethod() {
        // compiler error: "Type mismatch: cannot convert from Object to Country"
        Country c = this.getSingleResult(query, Country.class);
    }
}

我很困惑为什么会出现这个编译器错误,当然它应该使用Country 作为&lt;T&gt; 的值,而它似乎使用Object,我认为这是默认值&lt;E&gt; 当我没有指定参数类型时。

更奇怪的是,如果我将子类定义更改为public class MatchingAlgorithmManagerImpl extends AbstractManager&lt;Object&gt;,错误就会消失。

为什么我为E 定义的类型有任何相关性?

【问题讨论】:

  • query.getSingleResult() 返回什么?你没有看到 ClassCastException,对吧?
  • 它返回一个对象,但我将它动态转换为&lt;T&gt;
  • 啊,是的,你也写了它不能编译,并不是说它在运行时失败......
  • 确实编译失败,为什么你认为它在运行时会失败?
  • 如果你给 clazz.cast 提供了错误的类型,它会在运行时失败。但是当然,它只能在编译后在运行时失败;)

标签: java generics


【解决方案1】:

当您使用原始类型时,编译器确实会删除所有泛型类型,包括与类参数类型相关的那些(在您的情况下为E),以及那些不相关的(在您的情况下为T)。

因此,如果您不对扩展程序进行参数化,即使您的 T 也会被删除(这是动词吗?)为 Object,这就解释了错误。

可以从Non-generic reference to generic class results in non-generic return types找到好的参考

【讨论】:

  • 这是非常令人惊讶的行为,也是非常不可取的。我知道您应该始终为泛型类提供类型参数,但我发现 extends AbstractManagerextends AbstractManager&lt;Object&gt; 的含义不同,这让我感到非常惊讶
  • @Don:Java 中的原始类型(没有尖括号并且只为向后兼容而存在)和泛型类型之间有明显的区别。它们不应该混合在一起。始终声明您的类型。我不认为AbstractManagerAbstractManager&lt;Object&gt; 不一样是个问题……不过,这很奇怪,这延伸到像这种通用方法这样的东西t 使用类级别的类型参数。
【解决方案2】:

您的 AbstractManager 类声明包含一个泛型参数,但是当您扩展该类时,您使用的是原始类型, 试试

public class MatchingAlgorithmManagerImpl extends AbstractManager<Country>

【讨论】:

  • 但是 Country 肯定会是为 而不是 提供的值?我认为您可能需要再次阅读该问题(无意冒犯)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多