Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8289289

Add the `null`‑coalescing operator (`a ?? b`)

    XMLWordPrintable

Details

    • generic
    • generic

    Description

      A DESCRIPTION OF THE PROBLEM :
      Component: `specification`
      Subcomponent: `language`
      Labels: `amber`

      ---------------------------------------------

      The code `a != null ? a : b` is relatively common, but when `a` is a field load or a method call, then it’s not exactly correct, as a field could be modified by a thread race, and a method call could return a different value.

      A more correct version is:
      ```java
      { final var _a = a; result = _a != null ? _a : b; }
      ```

      But this version still doesn’t produce ideal bytecode, especially when `a != null ? a : b` is used multiple times in a sub‑expression.

      ---------------------------------------------

      Having a dedicated operator for this common‑ish case would allow the compiler to emit more compact bytecode for this:

      ```java
      return Foo.a() ?? Foo.b();
      ```

      ```jasm
      0 invokestatic Foo.a:()LBar; // stack: a:LBar;
      3 dup; // stack: a:LBar; a:LBar;
      4 ifnonnull L10; // stack: a:LBar;
      6 pop; // stack:
      7 invokestatic Foo.b:()LBar; // stack: b:LBar;
      10 L10: areturn;
      ```

      The `null`‑coalescing operator can be chained:

      ```java
      return Foo.a() ?? Foo.b() ?? Foo.c();
      ```

      ```jasm
      0 invokestatic Foo.a:()LBar; // stack: a:LBar;
      3 dup; // stack: a:LBar; a:LBar;
      4 ifnonnull L17; // stack: a:LBar;
      6 pop; // stack:
      7 invokestatic Foo.b:()LBar; // stack: b:LBar;
      10 dup; // stack: b:LBar; b:LBar;
      11 ifnonnull L17; // stack: b:LBar;
      13 pop; // stack:
      14 invokestatic Foo.c:()LBar; // stack: c:LBar;
      17 L17: areturn;
      ```

      ---------------------------------------------

      This operator is different from `Objects.requireNonNullElse(a, b)`, as `Objects.requireNonNullElse` evaluates both `a` and `b`, regardless of the nullity of `a`, and requires at least one of them to be non‑`null`.

      `Objects.requireNonNullElseGet(a, () => b)` is closer, in that evaluation of `b` is deferred, but `Objects.requireNonNullElseGet` requires `b` to be non‑`null`, whereas the `a ?? b` operator allows `b` to be `null` (in the same way that `a || b` allows `b` to be `false`).

      ---------------------------------------------

      This RFE is different from JDK-4151957, as that asks for a `null`‑safe field access or method call operator, which would be misused, as Java doesn’t currently have a notion of a non‑`null` or `null`able type, whereas the `??` operator requires having a valid non‑`null` reference in order for field access or method calls to not throw a `NullPointerException`.


      Attachments

        Activity

          People

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: