我的一些 Java 作业遇到了麻烦。我只是无法理解这些泛型的概念。
问题是:
假设以下是类中的方法头:
public <T implements Comparable <T>>T greatest(T arg1, T arg2)
找出错误?
我真的不明白怎么走。
要使这些东西编译,您必须按以下方式修改:
public <T extends Comparable <T>> T greatest(T arg1, T arg2)
Comparable 是一个接口,但在这种情况下,extends 用于表示“扩展”(用于类)或“实现”(用于接口)。
错误是您不能在方法签名中使用关键字实现。仅在类声明中。这两个编译:
public <T extends Comparable<T>>T greatest(T arg1, T arg2){
return null;
}
public <T extends String>T greatest(T arg1, T arg2){
return null;
}
我非常需要对此进行解释,因为我真的不明白该怎么走。
假设您希望我们解释签名的含义...
这可以分为两部分:
public <T ...> T greatest(T arg1, T arg2)
这意味着这greatest
是一个方法,它接受两个与某种类型兼容的赋值实例T
,并返回一个相同类型的实例。(从名称greatest
可以合理地猜测返回的值是两个参数中的较大者。)
第二部分是这样的(假设语法错误已更正):
<T extends Comparable<T>>
这意味着该类型T
必须实现Comparable
接口T
作为其类型参数。现在,如果您查看 Comparable 的 javadocs,您会发现它只有一个方法:
public int compareTo(T other);
它被指定为比较this
并other
返回一个小于零、零或大于零的数字,具体取决于this
(分别)是否小于、等于或大于other
。(阅读 javadoc!)
所以基本上这就是说T
必须是一个有compareTo
方法的类。显而易见的意图是该greatest
方法将使用该compareTo
方法来确定其 2 个参数中的哪个更大......并返回它。
至于解释语法,有两种可能的答案:
语法规则就是语法规则。您只需服从它们,否则您的程序将无法编译。
JLS 设计者此时必须在使用implements
或extends
使用通用语法,或使用一些新的关键字或符号之间做出选择:
添加新的关键字或符号对语言/工具链的其他部分影响太大,因此它们被“淘汰”。
允许使用implements
orextends
是多余的,可能会导致不必要的混淆。
根据implements
orextends
关键字的其他用法,(IMO)没有关于这些选择中哪个更好的令人信服的论据。如果他们基于抛硬币决定,我不会感到惊讶......
纠正错字后,它编译得很好。
当然,您可以使用Comparable<? super T>
.
我曾经写过一个非常相似的实用方法,你可以在这里找到: