为什么没有什么可以覆盖的,但仍然可以放置 @Override 而不会出现语法错误?

nhu*_*uvy 28 java java-17

我在 JDK 19 上使用 Java 语言级别 17。我有

package ocp17.ch07;

public record BeardedDragon(boolean fun) {
    
    @Override
    public boolean fun() {
        return false;
    }
    
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

为什么没有什么可以覆盖,但仍然可以放置@Override而没有语法错误?

use*_*er7 32

您确实覆盖了该fun方法(在本例中这很糟糕1)。对于 Java 记录,访问器名称(它自动为您提供)没有前缀get- 它是fun()而不是getFun()isFun()

JLS 的记录会员部分指出

此外,对于每个记录组件,记录类都有一个与记录组件同名的方法和一个空的形参列表。这种显式或隐式声明的方法称为访问器方法。

JEP 记录还说,

@Override 注释的含义已扩展为包括注释方法是记录组件的显式声明访问器方法的情况。

@Sweeper 的回答指出了 JLS 的相应部分

因此,无论您现在所做的是什么,都将被视为压倒一切。


1为什么不好?

假设你有一个BeardedDragon类似的例子,

BeardedDragon dragon = new BeardedDragon(true);
if (dragon.fun()) {
     System.out.println("Yay!!");
} else {
    System.out.println("Dang it.. It was supposed to be fun");
}
Run Code Online (Sandbox Code Playgroud)

当你调用时它会返回falsefun()。我不确定这是否是你想要的。

此外,它还违反了 JLS 的以下要求。

考虑一个记录类 R,它具有组件 c1、...、cn、每个组件的隐式声明的访问器方法以及隐式声明的 equals 方法。如果通过以下方式复制 R 的实例 r1:

R r2 = new R(r1.c1(), r1.c2(), ..., r1.cn());

然后,假设 r1 不是空引用,则表达式 r1.equals(r2) 的计算结果始终为 true。显式声明的访问器方法和 equals 方法应遵守此不变式。编译器通常不可能检查显式声明的方法是否遵循不变式。

使用@Johannes Kuhn 的示例(来自评论)。

var b1 = new BeardedDragon(true); 
var b2 = new BeardedDragon(b1.fun()); 
assert b1.equals(b2); // This will fail 
Run Code Online (Sandbox Code Playgroud)

  • 正确的!JLS 规定: *“此外,对于每个记录组件,记录类都有一个与记录组件同名的方法和一个空的形式参数列表。这种显式或隐式声明的方法称为访问器方法."* (3认同)
  • @Michael因为访问器可能希望在将可变组件(例如数组或可变集合)返回给调用者之前为其创建防御性副本。对于具有可变组件的记录(例如,ArrayList),该记录可能想要实现两组有效但不同的语义,并且两者都应该是可表达的。 (3认同)
  • 是的。也许您可以补充说,这些方法是由编译器自动生成的,并且您正在覆盖*那些*。因此,虽然这并不明显,但你仍然是压倒一切的。 (2认同)
  • @Thiyagu - 在这个阶段最好引用 JLS 17 而不是 JEP。记录不再是预览功能,因此 JLS 现在是最终的信息来源。 (2认同)

Swe*_*per 16

一些东西需要重写,即记录组件的访问器fun。这也是一种方法,叫做fun。不过,我同意这与重写超类中的方法不同,这是@Override最常用的方式。

规范的部分讨论了这一点@Override

关于记录类的子句是由于记录声明中 @Override 的特殊含义所致。即,它可以用于指定方法声明是记录组件的访问器方法。考虑以下记录声明:

record Roo(int x) {
    @Override
    public int x() {
        return Math.abs(x);
    }
}
Run Code Online (Sandbox Code Playgroud)

在访问器方法 int x() 上使用 @Override 可确保如果记录组件 x 被修改或删除,则相应的访问器方法也必须被修改或删除。

  • @ernest_k 不。规范说这是一个“特殊含义”,因此它是一个仅用于记录组件的“硬编码”构造。第 8.10 节(记录)也没有提到任何匿名类,例如枚举部分中的匿名类。 (5认同)