Details
-
Enhancement
-
Resolution: Won't Fix
-
P4
-
None
-
19
-
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 fromJDK-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`.
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