Abstract data on a blue backgroundData 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 calling super(..) 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.