【发布时间】:2018-06-19 20:17:53
【问题描述】:
背景:问题出现在this answer(确切地说,是答案的第一个修订版)。此问题中提供的代码已简化为解释问题的最低限度。
假设我们有以下代码:
public class Sample<T extends Sample<T>> {
public static Sample<? extends Sample<?>> get() {
return new Sample<>();
}
public static void main(String... args) {
Sample<? extends Sample<?>> sample = Sample.get();
}
}
它在没有警告的情况下编译并且执行良好。但是,如果有人试图以某种方式在get() 中明确定义return new Sample<>(); 的推断类型,编译器会抱怨。
到目前为止,我的印象是菱形运算符只是一些语法糖,不能编写显式类型,因此总是可以用一些显式类型替换。对于给定的示例,我无法为返回值定义任何显式类型以使代码编译。是否可以显式定义返回值的泛型类型或者在这种情况下是否需要菱形运算符?
下面是我尝试用相应的编译器错误显式定义返回值的泛型类型。
return new Sample<Sample> 结果:
Sample.java:6: error: type argument Sample is not within bounds of type-variable T
return new Sample<Sample>();
^
where T is a type-variable:
T extends Sample<T> declared in class Sample
Sample.java:6: error: incompatible types: Sample<Sample> cannot be converted to Sample<? extends Sample<?>>
return new Sample<Sample>();
^
return new Sample<Sample<?>> 结果:
Sample.java:6: error: type argument Sample<?> is not within bounds of type-variable T
return new Sample<Sample<?>>();
^
where T is a type-variable:
T extends Sample<T> declared in class Sample
return new Sample<Sample<>>(); 结果:
Sample.java:6: error: illegal start of type
return new Sample<Sample<>>();
^
【问题讨论】:
-
您写
public static Sample<? extends Sample<?>> get()而不仅仅是public static Sample<?> get()有什么特别的原因吗?在我看来,您已经以类型参数必须扩展Sample自身的方式定义了Sample。该声明对我来说似乎是多余的,如果您无法使两个?值匹配,可能会导致问题。 -
@DawoodibnKareem 看看上面提到的答案(及其问题)。它是在编写构建器和在构建器之间使用继承的背景下出现的。
-
不,我觉得链接的问题中没有任何内容可以证明将
extends子句添加到该方法签名中是合理的。尝试使get返回一个Sample<?>。 -
@DawoodibnKareem 忘记我刚刚写的内容。这是一个脑放屁。对于具体问题,您似乎是正确的。我的问题仍然存在:这是需要
<>的情况吗? -
我认为
Sample<?>和Sample<? extends Sample<?>>是等价的类型。参见例如ideone.com/XkOkZf。不过,我想不出一种直接的方式来解释这里发生了什么。
标签: java generics type-inference