Data classes

Stephen Colebourne scolebourne at
Wed Nov 8 19:39:36 UTC 2017

Like Mark and Remi, I think nullability is a key missing element.
While a language-wide approach to nullability would be nice, it isn't
needed to meet the need here. I agree with the points being made that
null interacts with hashCode, equals and toString, as well as
construction and getters. Data classes can't avoid dealing with null.

A couple of options:

Option1: All data class fields must be non-null

This is nice and simple. The constructor would validate all fields are
non-null. Optional<T> would be used for optional things. There would
be no impact on the wider language, its just that when you call a
getter you know that the result is non-null and doesn't need to be

Option 2: Fields on data classes can be marked as non-null or nullable

This is more complex. It could be via annotation or some other
syntactic form. It triggers the constructor to perform validation as
necessary, and alters the hashCode/equals/toString generation. But as
with option 1, there is no impact on the wider language.

If Optional<T> is going to be a value type at some point, then I think
option 1 is the simplest and neatest, and punts on nullability as a
general language feature, which is a good thing at this point.

But I definitely think that there is no need to do full nullity
propagation. I can say this with confidence because I have 3+ years
experience with a codebase where all data-like classes (beans) expose
only non-null values (in Java 8 where there is no nullity
propagation). While this is seemingly a small step, it turns out that
it vastly simplifies the rest of the codebase, as you tend to
completely forget null is a problem in the language. ie. there would
be no compiler protection against checking for null on the output of a
data-like class, but in practice that doesn't matter.

In general though, I like data classes. Devil in the detail and all that :-)

On 8 November 2017 at 16:29, Mark Raynsford <mark at> wrote:
> On 2017-11-03T13:19:09 +0100
> forax at wrote:
>> Yes, the point is about encapsulation, boundaries, as you have written.
>> We used to insert Objects.requireNonNull at the start of public methods to validate preconditions, given that the primary constructor of a data class is now generated, the question is how to tell the compiler to generate those precondition for me.
> Having played around with the prototype today, I have to say that I
> think Rémi might be right!
> It's what I think of as the Haskell effect: When you have a language
> with very terse syntax, every single piece of boilerplate you have to
> write seems a lot worse than it otherwise would. If you take a look at
> a typical Haskell file, it somewhat ironically feels as though there's
> quite a bit of boilerplate (typeclass instances, module export lists,
> matching on record values, signatures to some extent) because the rest
> of the language requires so few keystrokes.
> Having used data classes a little, I can see that I'm now almost never
> going to use the default constructor because I always want to insert
> calls to Objects.requireNonNull(...). Those have become the new
> mildly annoying boilerplate (and yet I'm used to having to write them
> over and over by hand in normal classes today).
> --
> Mark Raynsford |

More information about the amber-spec-observers mailing list