Check if returned value is not null and if so assign it, in one line, with one method call
Asked Answered
F

9

110

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?

Footlambert answered 9/4, 2015 at 11:45 Comment(1)
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.Woolworth
R
95

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.

Rusty answered 9/4, 2015 at 11:50 Comment(1)
work like i expected, however my IDE ( android studio ) ask me to remove it under the title of "duplicated initialization " ....Neocolonialism
D
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.

Divisible answered 28/6, 2016 at 19:4 Comment(5)
If getFreerangeChicken() is costly, make sure to use dinner = Optional.ofNullable(cage.getChicken()) .orElseGet(()->getFreerangeChicken());Lehet
this was useful in a websocket client: javax.websocket.CloseReason.getReasonPhrase() returns null on successful messagesAdvisee
Too bad it's discouraged. I kinda like it.Grilled
@PieterDeBie Why is this discouraged?Collateral
@HeatherSawatsky, I think just because, as the poster of this answer notes, you allocate an entire new Optional object every time you use it, so it's more expensive than just checking if it's null yourself.Howler
R
95

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.

Rusty answered 9/4, 2015 at 11:50 Comment(1)
work like i expected, however my IDE ( android studio ) ask me to remove it under the title of "duplicated initialization " ....Neocolonialism
J
39

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.

Joseph answered 28/8, 2018 at 17:41 Comment(0)
G
25

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())
Grilled answered 21/10, 2016 at 8:9 Comment(6)
why not with java 8?Gyratory
Java 8 has Optional, which doesn't require an external dependency. You can still use this of course.Grilled
Good answer, for example when you develop for Android pre API 24, where Optional calls are not available.Millrun
ObjectUtils also offers firstNonNull(cage.getChicken(),getFreeRangeChicken()), which reads nicer IMO, and allows longer fallback chains.Camelback
No because with this both getChicken() and getFreeRangeChicken() are computed, and according to the question only one has to be computed (if - else).Pleo
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().Grilled
A
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.

Arctic answered 9/4, 2015 at 11:51 Comment(0)
M
10

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() ;-)

Millrun answered 21/11, 2017 at 12:24 Comment(0)
S
0
dinner = cage.getChicken();
if(dinner == null) dinner = getFreeRangeChicken();

or

if( (dinner = cage.getChicken() ) == null) dinner = getFreeRangeChicken();
Saccule answered 9/4, 2015 at 11:50 Comment(3)
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.Puttee
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.Devorahdevore
i find the first part of the answer the best solution, its clear and easy to understand and only one call to getChicken is madeHildahildagard
A
0

You could use

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

even nicer with static import:

import static java.util.Objects.requireNonNullElseGet;

requireNonNullElseGet(cage.getChicken(), () -> getFreerangeChicken())
Adorn answered 1/10, 2021 at 7:58 Comment(4)
(*) Not valid for Java 1.8Lammas
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.Ozzie
This is just a worse version of the answer in https://mcmap.net/q/194828/-check-if-returned-value-is-not-null-and-if-so-assign-it-in-one-line-with-one-method-call.Joseph
Fixed the answer. I don't know what was going through my head when I typed this previously...Adorn
I
-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

Interbedded answered 19/6, 2015 at 9:48 Comment(1)
If the OP's objective was to prevent clutter, you only managed to worsen the problem.Lammas

© 2022 - 2024 — McMap. All rights reserved.