使用泛型返回类型

时间:2016-04-15 18:53:04

标签: java generics return-type

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

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

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

更新:我在Java教程中找到了关于generic methods的简明劝告。

  

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

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

  1. 方法的两个(或更多)参数类型之间存在依赖关系。
  2. 方法的返回类型与其参数类型中的一个(或多个)之间存在依赖关系。
  3. 显然,有问题的简单代码在其参数和返回类型之间没有依赖关系,因为没有参数。因此,通用方法是不合适的。

    UPDATE2:现在我已经意识到这一点,我在开源项目中注意到这种反模式的例子。

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

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

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

1 个答案:

答案 0 :(得分:6)

我认为你误解了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;
}