107

Java is littered with statements like:

if(cage.getChicken() != null) {
    dinner = cage.getChicken();
} else {
    dinner = getFreeRangeChicken();
}

Which takes two calls to getChicken() before the returned object can be assigned to dinner.

This could also be written in one line like so:

dinner = cage.getChicken() != null? cage.getChicken() : getFreeRangeChicken();

But alas there are still two calls to getChicken().

Of course we could assign a local variable then use the ternary operator again to assign it if it is not null, but this is two lines and not so pretty:

FutureMeal chicken = cage.getChicken();
dinner = chicken != null? chicken : getFreeRangeChicken();

So is there any way to say:

Variable var = some value if some value is not null OR some other value;

And I guess I'm just talking syntax here, after the code is compiled it probably doesn't make much difference how the code was written in a performance sense.

As this is such common code it'd be great to have a one-liner to write it.

Do any other languages have this feature?

user1803551
  • 12,965
  • 5
  • 47
  • 74
Continuity8
  • 2,403
  • 4
  • 19
  • 34
  • 4
    Not really an answer but if your code is full of such blocks of code replacing missing values with default one, there's probably a problem in the design of your API. – Denys Séguret Apr 09 '15 at 11:50

9 Answers9

97

Same principle as Loki's answer but shorter. Just keep in mind that shorter doesn't automatically mean better.

dinner = Optional.ofNullable(cage.getChicken())
  .orElse(getFreerangeChicken());

Note: This usage of Optional is explicitly discouraged by the architects of the JDK and the designers of the Optional feature. You are allocating a fresh object and immediately throwing it away every time. But on the other hand it can be quite readable.

jhyot
  • 3,733
  • 1
  • 27
  • 44
91

Java lacks coalesce operator, so your code with an explicit temporary is your best choice for an assignment with a single call.

You can use the result variable as your temporary, like this:

dinner = ((dinner = cage.getChicken()) != null) ? dinner : getFreeRangeChicken();

This, however, is hard to read.

Nicolai Parlog
  • 47,972
  • 24
  • 125
  • 255
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    work like i expected, however my IDE ( android studio ) ask me to remove it under the title of "duplicated initialization " .... – MoxGeek Nov 19 '20 at 12:58
33

Since Java 9 you have Objects#requireNonNullElse which does:

public static <T> T requireNonNullElse(T obj, T defaultObj) {
    return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
}

Your code would be

dinner = Objects.requireNonNullElse(cage.getChicken(), getFreeRangeChicken());

Which is 1 line and calls getChicken() only once, so both requirements are satisfied.

Note that the second argument cannot be null as well; this method forces non-nullness of the returned value.

Consider also the alternative Objects#requireNonNullElseGet:

public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)

which does not even evaluate the second argument if the first is not null, but does have the overhead of creating a Supplier.

user1803551
  • 12,965
  • 5
  • 47
  • 74
22

If you don't mind to use commons-lang you can use org.apache.commons.lang3.ObjectUtils#defaultIfNull

Your code would be:

dinner = ObjectUtils.defaultIfNull(cage.getChicken(),getFreeRangeChicken())
Durgesh Suthar
  • 2,914
  • 4
  • 19
  • 22
Pieter De Bie
  • 1,074
  • 13
  • 30
  • why not with java 8? – phil294 Feb 26 '17 at 00:41
  • Java 8 has Optional, which doesn't require an external dependency. You can still use this of course. – Pieter De Bie Feb 26 '17 at 09:29
  • Good answer, for example when you develop for Android pre API 24, where `Optional` calls are not available. – Levite Nov 21 '17 at 11:37
  • 2
    ObjectUtils also offers ```firstNonNull(cage.getChicken(),getFreeRangeChicken())```, which reads nicer IMO, and allows longer fallback chains. – Joachim Lous Jun 12 '20 at 08:17
  • 1
    No because with this both getChicken() and getFreeRangeChicken() are computed, and according to the question only one has to be computed (if - else). – Flyout91 Jul 16 '21 at 12:52
  • The problem in the original question was that he had to execute cage.getChicken() two times. Not that he executed both cage.getChicken() and getFreeRangeChicken(). – Pieter De Bie Jul 16 '21 at 12:57
12

Using Java 1.8 you can use Optional

public class Main  {

    public static void main(String[] args) {

        //example call, the methods are just dumb templates, note they are static
        FutureMeal meal = getChicken().orElse(getFreeRangeChicken());

        //another possible way to call this having static methods is
        FutureMeal meal = getChicken().orElseGet(Main::getFreeRangeChicken); //method reference

        //or if you would use a Instance of Main and call getChicken and getFreeRangeChicken
        // as nonstatic methods (assume static would be replaced with public for this)
        Main m = new Main();
        FutureMeal meal = m.getChicken().orElseGet(m::getFreeRangeChicken); //method reference

        //or
        FutureMeal meal = m.getChicken().orElse(m.getFreeRangeChicken()); //method call


    }

    static Optional<FutureMeal> getChicken(){

        //instead of returning null, you would return Optional.empty() 
        //here I just return it to demonstrate
        return Optional.empty();

        //if you would return a valid object the following comment would be the code
        //FutureMeal ret = new FutureMeal(); //your return object
        //return Optional.of(ret);            

    }

    static FutureMeal getFreeRangeChicken(){
        return new FutureMeal();
    }
}

You would implement a logic for getChicken to return either Optional.empty() instead of null, or Optional.of(myReturnObject), where myReturnObject is your chicken.

Then you can call getChicken() and if it would return Optional.empty() the orElse(fallback) would give you whatever the fallback would be, in your case the second method.

Loki
  • 4,065
  • 4
  • 29
  • 51
8

Use your own

public static <T> T defaultWhenNull(@Nullable T object, @NonNull T def) {
    return (object == null) ? def : object;
}

Example:

defaultWhenNull(getNullableString(), "");

 

Advantages

  • Works if you don't develop in Java8
  • Works for android development with support for pre API 24 devices
  • Doesn't need an external library

Disadvantages

  • Always evaluates the default value (as oposed to cond ? nonNull() : notEvaluated())

    This could be circumvented by passing a Callable instead of a default value, but making it somewhat more complicated and less dynamic (e.g. if performance is an issue).

    By the way, you encounter the same disadvantage when using Optional.orElse() ;-)

Levite
  • 17,263
  • 8
  • 50
  • 50
0
dinner = cage.getChicken();
if(dinner == null) dinner = getFreeRangeChicken();

or

if( (dinner = cage.getChicken() ) == null) dinner = getFreeRangeChicken();
crashxxl
  • 682
  • 4
  • 18
  • Missing curly braces aside, using an assignment within an evaluation shouldn't be legal IMHO. This code is just too hard to read and too easy to get wrong. – Jan Groth Apr 09 '15 at 12:12
  • While this may answer the question it’s always a good idea to put some text in your answer to explain what you're doing. Read [how to write a good answer](http://stackoverflow.com/help/how-to-answer). – Jørgen R Apr 09 '15 at 12:33
  • 1
    i find the first part of the answer the best solution, its clear and easy to understand and only one call to getChicken is made – NikkyD Sep 14 '17 at 15:49
0

You could use

Objects.requireNonNullElseGet(cage.getChicken(), () -> getFreerangeChicken())

even nicer with static import:

import static java.util.Objects.requireNonNullElseGet;

requireNonNullElseGet(cage.getChicken(), () -> getFreerangeChicken())
Datz
  • 3,156
  • 3
  • 22
  • 50
  • (*) Not valid for Java 1.8 – andreszs Jun 07 '22 at 20:01
  • 3
    This will evaluate both functions on every call since it's the result that gets passed in not a method reference. It would be better to use `Objects.requireNonNullElseGet(cage.getChicken(), () -> getFreeRangeChicken());` which will only call the supplier if the first object is null. – Michael Sep 05 '22 at 06:57
  • This is just a worse version of the answer in https://stackoverflow.com/a/52063580/1803551. – user1803551 May 02 '23 at 13:58
  • Fixed the answer. I don't know what was going through my head when I typed this previously... – Datz May 03 '23 at 07:08
-1

Alternatively in Java8 you can use Nullable or NotNull Annotations according to your need.

 public class TestingNullable {
        @Nullable
        public Color nullableMethod(){
            //some code here
            return color;
        }

        public void usingNullableMethod(){
            // some code
            Color color = nullableMethod();
            // Introducing assurance of not-null resolves the problem
            if (color != null) {
                color.toString();
            }
        }
    }

 public class TestingNullable {
        public void foo(@NotNull Object param){
            //some code here
        }

        ...

        public void callingNotNullMethod() {
            //some code here
            // the parameter value according to the explicit contract
            // cannot be null
            foo(null);
        }
    }

http://mindprod.com/jgloss/atnullable.html

Dan Jay
  • 874
  • 10
  • 27