New JEP draft proposes enhancements for Java with records and sealed types

java

Brian Goetz is one of the Chief Java Language Architects at Oracle and is usually only involved with big, important features in the JDK development. So, when we saw his name in a newly submitted JEP draft, we knew it would be some juicy news for Java developers!

Java has been often criticized for being too verbose and Java architects seem to be taking some of this criticism to heart. The draft submitted by Goetz on “Records and Sealed Types” aims to make Java code that models simple data aggregates easier to write, read, and to be corrected.

Let’s have a closer look.

Description

The JEP contains two new language constructs. Firstly, Java is to be extended by so-called records. Records are supposed to provide a new, compact syntax for the declaration of classes that are “transparent holders for shallowly immutable data.”

On the other hand, we have the “sealed types” with which classes and interfaces can be declared that restrict who their subtypes are. These two features are often implemented together in other languages under the name “algebraic data types”.

Records

A new kind of type declaration to the Java Language is proposed: records. Like an enum, a record is a restricted form of class – it declares its representation and commits to an API that matches that representation. Records will give up a key degree of freedom that classes usually enjoy – the ability to decouple a classes API from representation. In return, they gain a significant degree of concision. A record is “the state, the whole state, and nothing but the state.”

In Brian’s proposal, a record has the following form:

record Point(int x, int y) { }

It has a name, a state description, and a body. Most of the standard members are supposed to be derived mechanically, especially the representation and the protocols for construction, deconstruction equality and display.

Furthermore:

Records are classes; they can have most of the things other classes can: accessibility modifiers, Javadoc, annotations, an implements clause, and type variables, and the component declarations can have annotations. (The record, and the components, are implicitly final.) The body may declare static fields, static methods, static initializers, constructors, instance methods, instance initializers, and nested types.Brian Goetz

Sealed types

The second suggested feature for the implementation of algebraic data types are the sealed types. Two goals are to be achieved:

The first is to restrict which classes can be a subtype. Second, sealed types can allow “exhaustiveness analysis at the use-site, such as when switching over type patterns in a sealed type.”

The proposed syntax looks like this:

sealed interface Node
     permits A, B, C { ... }

Records and sealed types can be used together to model arithmetic expressions. Here again the example from the JEP draft:

sealed interface Expr { }

record ConstantExpr(int i) implements Expr { }
record PlusExpr(Expr a, Expr b) implements Expr { }
record TimesExpr(Expr a, Expr b) implements Expr { }
record NegExpr(Expr e) implements Expr { }

Motivation and goals

As mentioned earlier, Java has been criticized for being too verbose or having too much “ceremony”, as Goetz’s draft notes, and one of the reasons for that is classes that are nothing more than “plain data carriers”.  In order to write a simple data carrier class properly, you have to write a lot of low-value, repetitive, error-prone code like constructorsaccessorsequals()hashCode()toString(), etc. Therefore, this feature aims to make writing Java code that models simple data aggregates easier to write, read, and to be corrected.

However, some caution is advised since some may treat records as primarily being about boilerplate reduction while the feature has a more semantic goal – modeling data as data.

Non-goals

The draft clearly states that the goal of this feature is not to “declare war on boilerplate; in particular, it is not a goal to address the problems of mutable classes using the JavaBean naming conventions.”

Community discussion

Following the publication of this JEP draft, the discussion among Java developers has been hitting up.

While a significant number of developers welcome the new feature as long overdue, others voice some concerns mostly related to the author’s choice not to use this feature to deal with boilerplate-related complaints.

Why is it necessary for the author to state ‘It is not a goal to declare “war on boilerplate”‘? Boilerplate is one of the main criticism of Java, and Java language designers continue to downplay the problem. In my day job, I work with an app with 206k lines of Java code. The vast majority of it is boilerplate. When programs get to a certain size, too much boilerplate becomes a hinderance to management and understanding of the code base.

[“source=jaxenter”]