I am using Java language level 17 on JDK 19. I have
package ocp17.ch07;
public record BeardedDragon(boolean fun) {
@Override
public boolean fun() {
return false;
}
}
Why have nothing to override, but still can put @Override
without syntax error?
CodePudding user response:
You are indeed overriding the fun
method (which is bad in this case1). With Java records, the accessor name (which it automatically gives for you) doesn't have the get
prefix - it is fun()
and not getFun()
or isFun()
.
The Record Members section of JLS states
Furthermore, for each record component, a record class has a method with the same name as the record component and an empty formal parameter list. This method, which is declared explicitly or implicitly, is known as an accessor method.
The Records JEP also says,
The meaning of the @Override annotation was extended to include the case where the annotated method is an explicitly declared accessor method for a record component.
@Sweeper's answer points to the appropriate section of JLS for this
So whatever you've done now counts as overriding.
1 Why is it bad? It violates the below requirement.
Consider a record class R that has components c1, ..., cn, and an implicitly declared accessor method for every component, and an implicitly declared equals method. If an instance r1 of R is copied in the following way:
R r2 = new R(r1.c1(), r1.c2(), ..., r1.cn());
then, assuming r1 is not the null reference, it is always the case that the expression r1.equals(r2) will evaluate to true. Explicitly declared accessor methods and equals methods should respect this invariant. It is not generally possible for a compiler to check whether explicitly declared methods respect the invariant.
Even for the same instance,
BeardedDragon dragon = new BeardedDragon(true);
if (dragon.fun()) {
System.out.println("Yay!!");
} else {
System.out.println("Dang it.. It was supposed to be fun");
}
CodePudding user response:
There is something to override, namely the accessor for the record component fun
. That is also a method called fun
. Though, I agree that this is not the same kind of "override" as overriding a method in a superclass, which is how @Override
is most often used for.
The @Override
section of the spec talks about this.
The clause about a record class is due to the special meaning of @Override in a record declaration. Namely, it can be used to specify that a method declaration is an accessor method for a record component. Consider the following record declaration:
record Roo(int x) { @Override public int x() { return Math.abs(x); } }
The use of @Override on the accessor method int x() ensures that if the record component x is modified or removed, then the corresponding accessor method must be modified or removed too.