Records (preview): Why aren't accessor methods generated as final?

Jonas Konrad me at yawk.at
Fri Apr 24 21:34:09 UTC 2020


FYI, this is called an "explicit declaration" in the JEP: 
https://openjdk.java.net/jeps/359#Explicitly-declaring-members-of-a-record 
- it's not really related to final, because the explicit declaration 
happens in the same class, not a different one.

The javadoc of Record also gives one possible use case for explicit 
accessor declarations: Defensive copying of mutable members. Maybe 
someone else can name more.

Your example fails the copy invariant of Record. Sure, you can do it, 
just like you can implement a misbehaving .equals method, but behavior 
may be unpredictable.

- Jonas

On 4/24/20 11:04 PM, Mike Bishop wrote:
> I'm curious as to why the accessor methods in a record are not final.
> Consider the following record declaration:
> 
> public record Point(double x, double y) {}
> 
> The accessor methods x() and y() return x and y, respectively, but are not
> final. This allows me to override x(), for example, as follows:
> 
> public record Point(double x, double y) {
>      public double x() {
>          return x * x;
>      }
> }
> 
> I can test the above Point record with the following code to ensure that
> two Points with the same declared x and y coordinates are equal.
> 
> public static void main(String[] args) {
>      var p = new Point(3.0, 4.0);
>      var pPrime = new Point(p.x(), p.y());
>      System.out.println("p = " + p + ", pPrime = " + pPrime);
>      assert pPrime.equals(p);
> }
> 
> As expected, the assertion fails as pPrime is (9.0, 4.0) while p is (3.0,
> 4.0).
> 
> My concern is that if I'm using a Point in my code, I would expect that two
> Points with the same x and y will be equivalent since the 2-tuple (x, y)
> represents "the state, the whole state and nothing but the state" of Point.
> I think this can only be assured if the accessor methods are final.
> 
> Best regards,
> Mike Bishop
> 


More information about the amber-dev mailing list