小编典典

具有通用返回类型的方法中的Java编译错误

java

我无法解释为什么这个简单的代码无法编译。

class Foo {
    <T extends Foo> T method() {
        return this;
    }
}

错误是:Type mismatch: cannot convert from Foo to T
为什么不?T定义为Foo或其子类。


更新:我在Java教程中找到了关于泛型方法的简短建议。

通用方法允许使用类型参数来表示方法的一个或多个参数的类型和/或其返回类型之间的依赖性。如果没有这种依赖性,则不应使用通用方法。

我的解释是,通用方法仅适用于两种情况。

  1. 方法的两个(或多个)参数类型之间存在依赖关系。
  2. 方法的返回类型与其一个(或多个)参数类型之间存在依赖关系。

显然,所讨论的简单代码的参数和返回类型之间没有依赖关系,因为没有参数。因此,通用方法是不合适的。


UPDATE2:现在我知道了,我注意到开源项目中这种反模式的示例。


UPDATE3:我认为我发现了不涉及多个参数或返回类型的通用方法的要求。多重继承似乎是Java教程中上述规则的例外。

<T extends Foo & Bar> void method(T foobar) {
    // Call Foo method.
    // Call Bar method.
}

值得注意的是,Collectors实用程序类包括toList()不带参数的通用方法。在这种情况下,通用类型仅对返回类型进行参数化,这可能比实际用作返回类型的通用类型更安全。


阅读 190

收藏
2020-12-03

共1个答案

小编典典

我认为您误解了Java泛型的工作原理:

<T extends Foo> T method() {

这意味着该方法的 调用者 可以选择Foo他们想要的任何子类型并提出要求。例如,你可以写

Foo foo = new Foo();
SubFoo subfoo = foo.<SubFoo>method();

…并期望SubFoo返回,但是您的method实现无法返回SubFoo,而这将失败。(我不会讲Scala,但是我认为这意味着您的Scala实现实际上不是“等效的”。)

如果你希望你的方法能够返回的子类型Foo实现 选,而不是调用者,那么就写

Foo method() {
  return this;
}
2020-12-03