带有generics返回类型的方法中的Java编译错误
我无法解释为什么这个简单的代码不能编译。
class Foo { T method() { return this; } }
错误是: Type mismatch: cannot convert from Foo to T
为什么不? T
被定义为Foo
或其子类。
在相关的说明中,等效的Scala示例会进行编译,因此Java错误不是由于JVM的限制。
class Foo { def method[T <: Foo] = this }
更新:我在Java Tutorials中找到了关于generics方法的简明建议。
通用方法允许使用类型参数来表示方法和/或其返回类型的一个或多个参数的类型之间的依赖关系。 如果没有这种依赖关系,则不应使用通用方法。
我的解释是,通用方法仅适用于两种情况。
- 两个(或更多)方法的参数类型之间存在依赖关系。
- 方法的返回类型与其参数类型中的一个(或多个)之间存在依赖关系。
显然,有问题的简单代码在其参数和返回类型之间没有依赖关系,因为没有参数。 因此,通用方法是不合适的。
更新2:现在我已经意识到这一点,我在开源项目中注意到这种反模式的例子。
- co.cask.cdap.api.data.DatasetContext.getDataset()
- org.kitesdk.data.Datasets.load()
- com.fasterxml.jackson.databind.ObjectMapper.valueToTree()
更新3:我想我已经找到了一个不涉及多个参数或返回类型的generics方法的要求。 多重inheritance似乎是Java教程中上述规则的一个例外。
void method(T foobar) { // Call Foo method. // Call Bar method. }
值得注意的是, Collectors
实用程序类包括不带参数的toList()
等通用方法。 在这种情况下,generics类型仅参数化返回类型,这可能比实际返回类型的generics类型更安全。
我认为你误解了Javagenerics如何工作:
T method() {
这意味着该方法的调用者可以选择他们想要的任何Foo
子类型并请求它。 例如,你可以写
Foo foo = new Foo(); SubFoo subfoo = foo.method();
…并期望返回SubFoo
,但是您的method
实现无法返回SubFoo
,而这必须失败。 (我不会说Scala,但我认为这意味着你的Scala实现实际上并不是“等效的”。)
如果你希望你的方法能够返回实现选择的Foo
子类型,而不是调用者,那么只需写
Foo method() { return this; }