Java 14 records canonical constructor
Remi Forax
forax at univ-mlv.fr
Thu Jun 4 20:06:14 UTC 2020
----- Mail original -----
> De: "Christian Beikov" <christian.beikov at gmail.com>
> À: "amber-dev" <amber-dev at openjdk.java.net>
> Envoyé: Jeudi 4 Juin 2020 21:31:01
> Objet: Re: Java 14 records canonical constructor
> Am 04.06.2020 um 21:06 schrieb Remi Forax:
>>> This could be done through a static factory method as well.
>>>
>>> public record UserRecord(String userName, List<String> mailAddresses) {
>>> public static UserRecord create(String userName, List<String>
>>> mailAddresses) {
>>> return new UserRecord(userName, List.copyOf(mailAddresses));
>>> }
>>> }
>>>
>> Nope, because serialization is based on the canonical constructor.
>>
>> Rémi
>
> Not sure I understand the serialization argument. Can't you define a
> readResolve method for that purpose if you really want to ensure it uses
> a defensive copy for deserialization? Like this:
>
> public record UserRecord(String userName, List<String> mailAddresses) {
> public static UserRecord create(String userName, List<String>
> mailAddresses) {
> return new UserRecord(userName, List.copyOf(mailAddresses));
> }
>
> private Object readResolve() {
> return create(userName, mailAddresses);
> }
> }
>
Sorry to not have been clear, i was thinking about serialization in the general sense of the word, so not only internal Java serialization but also external serialization to JSON using jackson, to XML using JAXB, to SQL using hibernate, etc.
At some point, we may have to introduce the notion of factory method in the language, but currently this is not the case.
> Maybe the "compact named constructor" I mentioned before could be used
> to generate the static create method and the readResolve method?
>
> public record UserRecord(String userName, List<String> mailAddresses) {
> public UserRecord create {
> mailAddresses = List.copyOf(mailAddresses);
> }
> }
>
>
> Sorry if this is going to far. I'm just looking for a way to ensure that
> a record is really composed of just the record components such that the
> canonical constructor can't alter anything to avoid accidental bugs. If
> you say it's the programmers responsibility to ensure this, I'm fine
> with that. I'd be curious to know what you want to utilize this property
> of records for though :)
There is no way in Java to say that only idempotent functions are allowed*, so we rely on users not doing stupid things.
regards,
Rémi
* technically, you can use methods that are not idempotent in a canonical constructor see https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Record.html#%3Cinit%3E()
More information about the amber-dev
mailing list