3 ms·
The new object type being promoted from preview feature is just the record type. Records are still Objects, they just provide a low ceremony way to create an im
by papercrane 6y ago
The new object type being promoted from preview feature is just the record type. Records are still Objects, they just provide a low ceremony way to create an immutable object holding some data.
I see these record classes in the same category as enum objects, an evolution of the language to improve developer ergonomics.
Upcoming is inline-classes (previous called value types.) When this happens we'll have a true "special" kind of Object, one that does not have any identity. The motivation here is mostly performance. The details are available in Brian Goetz "State of Valhalla" update https://cr.openjdk.java.net/~briangoetz/valhalla/sov/01-background.html https://cr.openjdk.java.net/~briangoetz/valhalla/sov/01-back...
- avodonosov 6y agoEven if `record` is a syntactic sugar, I'd better see a canonical constructor added to all usual classes. The constructor parameters are of types of all the fields, in the declaration order. In this case we could say class Point { public final int x, y; } instead of record Point(int x, int y) { } Usual non-record classes would benefit greatly from such a feature too. Actually, if class fields have different visibility, several canonical constructors are needed. If public fields exist, a constructor that sets all public fields. If protected fields exist, a constructor that sets all public and protected fields. If package-private fields exist - setting all public, protected, and package-private fields. If private fields exist - setting all public, protected, package-private, and private fields. What remains, is value-oriented versions of equals(), hashCode() and toString() to be defined. Probably better to express as a base class than the new keyword `record`; class Point extends Record { public final int x, y; } A polyfill for such a base class for older Java: import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; class Record { @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this, true); } @Override public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj, true); } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } } I practice such classes in my code, for constructors, I just don't bother for final (Java does not support it well anyways), and have factory methods in a separate class, so they are out of the readers view.
- papercrane 6y agoAdding a new canonical constructor to all classes would very likely have backwards compatibility issues, so we'd likely need some sort of opt-in mechanism. In the end the language designers decided that they wanted to give developers a way to create a very focused kind of object. This goes into the design motivations: https://cr.openjdk.java.net/~briangoetz/amber/datum.html https://cr.openjdk.java.net/~briangoetz/amber/datum.html Additionally, one less talked about benefit of records is they have a simplified serialization scheme that is safer by default. Records when being deserialized have each of their members read and then the canonical constructor is called, if the values are not valid then the constructor can reject the fields instead of allowing an "impossible" object from being created.
- avodonosov 6y agoThe opt-in (or rather opt-out) could be a presence of user-defined constructor. The same way as with default no-arg constructor. Interesting note about serialization. That could also be part of the base class.