8

Java 14 brings records, which are a great addition seen in many functional languages:

Java:

public record Vehicle(String brand, String licensePlate) {}

ML:

type Vehicle = 
  {
    Brand : string
    LicensePlate : string
  }

In ML languages, it is possible to "update" a record by creating a copy with a few values changed:

let u = 
  {
    Brand = "Subaru"
    LicensePlate = "ABC-DEFG"
  }

let v =
  {
    u with 
      LicensePlate = "LMN-OPQR"
  }

// Same as: 
let v = 
  {
    Brand = u.Brand
    LicensePlate = "LMN-OPQR"
  }

Is this possible in Java 14?

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245

1 Answers1

6

Unfortunately, Java does not include this functionality. Though, you could create a utility method that takes in a different license plate value:

public static Vehicle withLicensePlate(Vehicle a, String newLicensePlate) {
    return new Vehicle(a.brand, newLicensePlate);
}

Used like so:

Vehicle a = new Vehicle("Subaru", "ABC-DEFG");
Vehicle b = Vehicle.withLicensePlate(a, "LMN-OPQR");

This would give you a similar result to what you were attempting using the "with" tag. And you can use this as a way to update the record.

sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
  • 6
    The correct declaration would be `public Vehicle(Vehicle a, String newLicensePlate) { this(a.brand, newLicensePlate); }` but it’s a bad pattern anyway. The constructor’s parameter types don’t indicates whether the argument is a new brand or new license plate and supporting constructors for both elements doesn’t work at all when both have the same type. A cleaner approach would be to add a *method* to the record, like `public Vehicle withLicensePlate(String newLicensePlate) { return new Vehicle(brand, newLicensePlate); }` which can be used like `Vehicle b = a.withLicensePlate("LMN-OPQR");` – Holger Feb 04 '21 at 18:08
  • @Holger I am not very used to ML, and as informed by OP the `with` pattern is something that's expected out of the box of records without the introduction of any new method. I almost formulated a similar design to that of your proposal [here](https://github.com/fortybits/a-bit-of-java/blob/bits/src/main/java/edu/bit/WithPatternInRecords.java), but in my (now deleted) answer I couldn't really match up to the OP's expectation I believe. – Naman Feb 04 '21 at 18:44
  • @Holger suggestion is what would be achieved automatically using `with`. It's disappointing Java doesn't support this; when a PL has "records", this feature is usually assumed. – sdgfsdh Feb 04 '21 at 20:07
  • 2
    @Naman I know that the OP asked for an automatism that unfortunately doesn’t exist (yet?). I just responded to the answer which suggested a constructor whereas a method would be much better. – Holger Feb 05 '21 at 09:15
  • @Holger just in case you are not _yet_ tired of me pinging you for questions that simply only you can respond to (imho), [here](https://stackoverflow.com/questions/66075419/which-part-of-the-jls-specifies-that-you-cant-cast-from-list-extends-listsup) is one – Eugene Feb 08 '21 at 16:34
  • 1
    FYI - I've written a library that generates "with"ers for Java 16 records: https://github.com/Randgalt/record-builder – Randgalt Mar 16 '21 at 21:07