我对接收器参数上下文中 override-equivalent (JLS 8.4.2)的定义有一个相当技术性的问题。
编辑:发布此问题后,关于接收器参数的评论中存在很多混淆。许多人似乎认为在下面的代码中使用名为this
的参数是非法的,因此误解了这个问题。如果您不了解此功能,请参阅https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.1。可以在这里找到一个更容易理解的解释:http://blog.joda.org/2015/12/explicit-receiver-parameters.html。这个问题非常技术性,适用于熟悉接收器参数且熟悉Java语言规范(JLS)的经验丰富的Java开发人员。
术语覆盖等效定义如下:
方法
m1
的签名是方法m2
签名的子签名,如果是:
- 具有相同的签名
m2
与m1
或m1
的签名与m2
签名的删除(§4.6)相同。两个方法签名
m1
和m2
是覆盖等效 iffm1
是m2
或m2
的子签名是m1
的副标记。
因此,如果我理解正确,下面这两个方法中的两个方法不是覆盖等价的,即使直觉上我也希望它们是:
class A {
void foo(A this) { /* ... */ }
void foo() { /* ... */ }
}
尽管如此,显然我不能在同一个类中声明这两个方法,当我尝试这样做时,编译器正确地抱怨已经定义了foo()
。
我的问题包括两部分:
答案 0 :(得分:2)
好的,我找到了答案,我就把它留在这里,希望有朝一日能帮助别人。
我的两部分问题的答案是:
不,原帖中的两种方法覆盖等效。
定义的相关部分是JLS 8.4.2的第一句话:
两个方法或构造函数
M
和N
如果具有相同的名称,相同的类型参数(如果有的话),则具有相同的签名({{3 }},并且,在将N
的形式参数类型调整为M
的类型参数后,使用相同的形式参数类型。
我已经读过那个部分,但我认为接收器参数虽然特殊,但也被认为是(一种特殊的)形式参数。因此我假设在调整形式参数类型(...)" 后,接收器参数隐含地包含在句子中#34; (...) (强调我的)。但事实并非如此。接收器参数不也是形式参数;相反,接收器参数和形式参数的定义是互斥的。因此,接收器参数不是上述引文中定义的方法签名的一部分。由于 override-equivalent 的定义使用了方法签名的定义,这也意味着我原始帖子中的两个方法实际上是覆盖等价的(因为它们确实如此)有相同的签名!)。
有关章节澄清了接收器参数确实不是正式参数,稍后会在§8.4.4部分稍后介绍:
receiver参数是实例方法或内部类构造函数的可选语法设备。对于实例方法,receiver参数表示调用该方法的对象。对于内部类的构造函数,receiver参数表示新构造的对象的直接封闭实例。无论哪种方式,接收器参数仅存在以允许在源代码中表示所表示的对象的类型,以便可以注释该类型。 接收器参数不是形式参数;更确切地说,它不是任何变量(JLS 8.4.2)的声明,它永远不会绑定到在方法调用表达式或限定类实例创建表达式中作为参数传递的任何值,并且它不会产生任何影响在运行时。
(强调我的)
接收器参数不是形式参数的声明在那一大块文本中有点丢失。