Blog
March 8, 2018OpenJDK: Amber Project
- Topics
- Services + APIs
Data Class: record
In an effort to improve developer productivity and to make Java less verbose, Amber Project will introduce record type to streamline data class generation.
Usage
Consider a data class used to describe information on latitude and longitude coordinates:
final class Coordinate {
public final double lat;
public final double lon;
// arg constructor
public Coordinate(double lat, double lon) {
this.lat = lon;
this.lon = lon;
}
// state-based implementations
public int hashCode() { ... }
public boolean equals(Object obj) { ... }
public String toString() { ... }
}
Beyond the field definitions, the bulk of the class is boilerplate code. Developers typically generate this using a modern IDE or through abstraction libraries, such as Lombok. Both of these can now be eliminated by using record
to define classes by their state.
record Coordinate(double lat, double lon) { }
Underneath, the compiler is creating a class file which mirrors the original Coordinate
class, except it now extends java.lang.DataClass
. Callers of Coordinate
can still invoke the public arg-constructor, fields and state-based methods.
Customization
Beyond the basic implementation, data classes can be further customized by overriding toString()
method and the default arg-constructor:
record Coordinate(double lat, double lon) {
@Override
public Coordinate(double lat, double lon) {
if (x < 0 || y < 0)
throw new IllegalArgumentException();
default.this(x, y);
}
@Override
public String toString() {
return "foo";
}
}
Also a new addition,
default.this(..)
is the equivalent of callingsuper(..)
without the order requirement.
Quirks
- No additional fields.
- Non-abstract data classes are immutable.
- Data classes with the same state are transitively equal.
- No override of
equals()
,hashCode().
- Data classes can only extend abstract data classes.
- Abstract data classes do not acquire
equals()
,hashCode()
,toString()
and must also have protected constructor. - No restriction on interfaces.
Extension
When a data class extends another abstract data class, the state of the data class must be declared as part of the record
definition.
abstract record Coordinate(double lat, double lon);
record Polar(double lat, double lon) extends Coordinate(lat, lon);
However, a concrete class can carry additional states not defined on the abstract class.
interface Coordinate {
abstract record Cartesian(double lat, double lon) implements Coordinate;
record Polar(double lat, double lon) extends Cartesian(lat, lon);
record Spherical(double x, double y, double z) extends Cartesian(x, y);
}
A data class cannot remove state from an abstract data class.
abstract record Coordinate(double lat, double lon);
record Line(double x) extends Coordinate(x); // does not compile
Release
Exact release date is not yet known, but this feature and others in Amber Project are tentatively scheduled to be merged into OpenJDK by the end of 2018 as part of Java 11. This is likely to change, given the volatility OpenJDK's new release strategy will introduce in 2018. Furthermore, Mark Reinhold stated at DevNexus 2018:
Features will be released when they are functionally complete.
This is a departure from previous release schedules and suggests a larger focus on quality over arbitrary timelines. Up-to-date information on this new feature and other projects can be found on OpenJDK's JEP Index.