Skip to main content
 首页 » 编程设计

java之具有接收者参数覆盖的方法是否等效于没有接收者参数的相同方法声明

2024年06月20日125sxdcgaq8080

我有一个关于接收器参数上下文中覆盖等效 ( 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 开发人员,他们熟悉接收器参数并且非常了解 Java 语言规范 (JLS)。

术语覆盖等效定义如下:

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

  • m2 has the same signature as m1, or
  • the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.

因此,如果我理解正确,下面类中的两个方法不是覆盖等效的,尽管直觉上我希望它们是:

class A { 
    void foo(A this) { /* ... */ } 
    void foo() { /* ... */ } 
} 

然而,显然我不能在同一个类中声明这两个方法,当我尝试这样做时,编译器会合理地提示 foo() 已经定义。

我的问题由两部分组成:

  1. 我是否正确理解上述两种方法不是覆盖等效的?
    • 如果不是:我错过了定义的哪一部分?
    • 如果是:JLS 中的什么规则正式禁止上述两个方法定义同时出现在同一个类中,因为在这种情况下它不能是规则 “声明两个是编译时错误类中具有覆盖等效签名的方法。” ( JLS 8.4.2 )

请您参考如下方法:

好的,我找到了答案,我就把它留在这里,希望有一天它能对某人有所帮助。

我的两部分问题的答案是:

  1. 不,原帖中的两个方法覆盖等效的。

  2. 定义的相关部分是JLS 8.4.2的第一句:

Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.

我读过那部分内容,但我假设接收方参数虽然特殊,但被视为(一种特殊的)形式参数。因此,我假设接收器参数隐式包含在句子“(...) after adapting the formal parameter types (...)”(强调我的)中。然而,事实并非如此。接收器参数不是也是形式参数;相反,接收方参数形式参数 的定义是互斥的。因此,接收者参数不是上述引用中定义的方法签名的一部分。由于 override-equivalent 的定义使用了 method signature 的定义,这也意味着我原来帖子中的两个方法实际上是 override-equivalent(因为它们确实有相同的签名!)。

澄清接收者参数确实不是形式参数的相关部分稍后出现在部分 JLS 8.4.2 中。 :

The receiver parameter is an optional syntactic device for an instance method or an inner class's constructor. For an instance method, the receiver parameter represents the object for which the method is invoked. For an inner class's constructor, the receiver parameter represents the immediately enclosing instance of the newly constructed object. Either way, the receiver parameter exists solely to allow the type of the represented object to be denoted in source code, so that the type may be annotated. The receiver parameter is not a formal parameter; more precisely, it is not a declaration of any kind of variable (§4.12.3), it is never bound to any value passed as an argument in a method invocation expression or qualified class instance creation expression, and it has no effect whatsoever at run time.

(强调我的)

接收者参数不是形式参数的声明在那一大堆文本中有点迷失了。