247

Is it possible to do something similar to the following code in Java

int y = x ?? -1;

More about ??

Ivar
  • 6,138
  • 12
  • 49
  • 61
Nikita Ignatov
  • 6,872
  • 2
  • 34
  • 34
  • 9
    Voting to reopen as not a duplicate. This question is "Does x exist" the other question is "Since x doesn't exist how do I get y". – jmoreno Jul 17 '15 at 23:02
  • 7
    On Java8+ has Optional class in jdk. Example of usage Optional.ofNullable(x).orElse(-1). Other good usage of usage Optional is method map. Let say there object a which is equivalent of json object: "a": {"b":{"c":1}}. To read c value can be such construction like: Optional.ofNullable(a).map(a->a.b).map(b->b.c).orElse(-1). Is much ugly literal syntax than C#, but it is better option that using cascading operator ?: – kikea Mar 13 '19 at 19:46
  • This works in C# only if x is a nullable int. either `Nullable x;` or `int? x`. if x is just int, its a compilation failure. – Code Name Jack Oct 12 '20 at 20:24
  • 1
    Another one for my C# vs. Java list. Can't believe there's not even an `Objects.coalesce(...)` or equivalent. – Josh M. Jan 30 '22 at 17:29
  • 2
    @JoshM. There is indeed a coalesce equivalent from Java 9 onwards. [Objects.requireNonNullElse](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Objects.html#requireNonNullElse(T,T)) and if you want short-circuiting behaviour there's [Objects.requireNonNullElseGet](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Objects.html#requireNonNullElseGet(T,java.util.function.Supplier)) – k314159 Apr 06 '22 at 09:55
  • 1
    @k314159 thank you. I looked at the API quickly and am sad to see that the `defaultObj` must be non-null. Also sad that it's named `require...` because it makes it sound like it's going to throw if the parameter is null, in reality it just returns the default object passed in. Poor naming. Should have been `coalesce` or similar. – Josh M. May 07 '22 at 18:56
  • 1
    @JoshM. Note that it *does* throw if the parameter is null and the default object/object supplier is also null. – g t Nov 28 '22 at 09:41
  • 1
    @gt sure, just another example of Java's overzealous null handling. Really annoying. – Josh M. Nov 29 '22 at 12:31

5 Answers5

193

Sadly - no. The closest you can do is:

int y = (x != null) ? x : -1;

Of course, you can wrap this up in library methods if you feel the need to (it's unlikely to cut down on length much), but at the syntax level there isn't anything more succinct available.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • 58
    Which of course only works if x is an `Integer` because an `int` cannot be compared to `null`. – musiKk Mar 07 '11 at 17:38
  • 4
    @musiKk: and the C# equivalent would only work on int? (or rather any reference type or nullable) – jmoreno Jul 17 '15 at 23:08
  • 1
    @jmoreno I am no C# developer so I have no idea. – musiKk Jul 18 '15 at 09:01
  • 2
    @musiKk: type? is how you declare a variable of a nullable type. The c# null coalescing operator only works on nullable or reference types. If the above example was C#, x would be of type int? -- but better written using the null coalescing operator as y=x?? -1; – jmoreno Jul 18 '15 at 15:17
  • 12
    @jmoreno Oh, I thought that was a question...... – musiKk Jul 18 '15 at 15:18
  • 20
    That's what `code blocks` are for so you can tell that `int?` is a data type, not a question. :) – ErikE Sep 16 '18 at 02:09
  • But x is evaluated twice (one for condition and one for assignation). When using null coalescing operator `int y = x ?? -1`, x is evaluated once. – ReaperSoon Oct 18 '21 at 15:49
68

The Guava library has a method that does something similar called MoreObjects.firstNonNull(T,T).

Integer x = ...
int y = MoreObjects.firstNonNull(x, -1);

This is more helpful when you have something like

int y = firstNonNull(calculateNullableValue(), -1);

since it saves you from either calling the potentially expensive method twice or declaring a local variable in your code to reference twice.

Valerio Bozz
  • 1,176
  • 16
  • 32
ColinD
  • 108,630
  • 30
  • 201
  • 202
  • 11
    Unfortunately this will throw a NullPointerException if all values are null. While coalesce can return null. – Stefan Jan 25 '14 at 18:00
  • 1
    @Stefan: True, though I did say it was "similar" not exactly the same. And this sort of thing is by far the most useful for (and the most used for) cases where you want a fixed, non-null default if something is null. Given that, `firstNonNull` fails if the second argument is null to help programmer errors be caught faster. – ColinD Jan 27 '14 at 18:37
  • 26
    The real issue with a solution like this is that it sacrifices the null coalesces lazy evaluation. Since all of the values have to be passed to `Objects.firstNonNull`, any functions you have passed will be evaluated. This makes it potentially far more computationally expensive than C#'s `??`. – Andrew Coonce Oct 27 '14 at 17:30
  • 1
    @AndrewCoonce: Sure, but there are a lot of use cases (like this example) where you just want a default or something that isn't expensive to compute. And when the alternative is expensive to compute, there's always the ternary. – ColinD Oct 27 '14 at 17:39
50

Short answer: no

The best you can do is to create a static utility method (so that it can be imported using import static syntax)

public static <T> T coalesce(T one, T two)
{
    return one != null ? one : two;
}

The above is equivalent to Guava's method firstNonNull by @ColinD, but that can be extended more in general

public static <T> T coalesce(T... params)
{
    for (T param : params)
        if (param != null)
            return param;
    return null;
}
usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305
31

ObjectUtils.firstNonNull(T...), from Apache Commons Lang 3 is another option. I prefer this becuase unlike Guava, this method does not throw an Exception. It will simply return null;

mateuscb
  • 10,150
  • 3
  • 52
  • 76
24

No, and be aware that workaround functions are not exactly the same, a true null coalescing operator short circuits like && and || do, meaning it will only attempt to evaluate the second expression if the first is null.

AkariAkaori
  • 427
  • 5
  • 4