Records and null-values

Brian Goetz brian.goetz at oracle.com
Sat Aug 24 12:57:16 UTC 2019


The recommended idiom here is to check for this in the constructor.  I know that sounds contrary to the goal of records — the point  is not to have an explicit constructor — but records have a streamlined constructor form that makes this only marginally verbose than what you suggest:

    record R(String s) { 
        public R { requireNonNull(s); }
   }

What is going on here is that you are allowed to omit the signature of the canonical constructor (it’s a record, we know what the canonical constructor should look like), and also, for any fields that are not definitely initialized by the constructor, they will be automatically initialized from the corresponding parameters.  (This can also be used to normalize parameters, as well as validate.)  So it’s a little more verbose, but it’s not terrible.(We’d like to make these auto-initializing constructors available to all classes someday, not just records.)  

Addressing the more general concern — I sympathize with the problem, but I can’t agree with the proposed solution.  First of all, remember that annotations are not, full stop, allowed to influence language semantics; they are intrinsically extralinguistic.  At best, they can be used to perform additional safety checks (like @Override), but this is as far as we can push the line.  (So conditioning runtime checks on compile-time annotations is right out.)  If the language wants to be aware of nullity, it needs to be part of the language, such as a `non-null` keyword or non-nullable types like `String!`.  This is a possibility, but it’s a huge effort, both for the language, and for the world of Java libraries (especially the JDK.)  

Which brings us to the real problem — this is not a simple hack.  Sure, we could hack something in for records, but that would be super-unsatisfying; surely, a facility that allows you to reject null arguments is useful and desirable beyond records.  (Not to mention that it would make it harder to migrate smoothly between classes and records.)  We would — correctly, this time — be greeted with a “glass 90% empty” reaction.  

It was even suggested, during the development of the feature, that reference components of records _always_ be non-nullable.  That would have been a terrible idea (though I understand the sort of pain that causes people to suggest such things.)

There are numerous static analysis frameworks that will use annotations to detect errors, and if you can use these, that’s great.  There’s a new effort brewing, being proposed by Google and Jetbrains, to coalesce around a set of nullity annotations and type checking rules, which was discussed at JVMLS this year.  But, this is not a small problem, and not one with a guaranteed solution; it safe to say this is an order of magnitude bigger than records.  So by all means, I support a more general solution, but hacking something in for records would be satisfying only for a few minutes, and thereafter would be disappointing. 

So, it’s a real problem, but not one that admits to simple solutions at the periphery.  

> On Aug 24, 2019, at 1:57 AM, Kasper Nielsen <kasperni at gmail.com> wrote:
> 
> Hi,
> 
> I was looking through a codebase trying to see where I could apply records.
> And I realised that there was not a single place where I did not check for
> null via requireNotNull() in the constructor. And looking at the use cases
> for records I'm sure most that is the case for most people.
> 
> I know @Nullable annotations don't get much love, and it might have some
> deeper implications in the language. But it would save a lot of boilerplate
> if you where able to do something like:
> 
> record R(Object key, @Nullable Object value) {}
> 
> being equivalent to the constructor declaration
> 
> record R(Object key, @Nullable Object value) {
>  R {
>    this.key = requireNonNull(key, "key is nul");
>    this.value = value;
>  }
> }
> 
> It would probably also prevent a couple of NPEs somewhere.
> 
> Best
>  Kasper



More information about the amber-dev mailing list