109

I am trying to simplify the following code.

The basic steps that the code should carry out are as follows:

  1. Assign String a default value
  2. Run a method
  3. If the method returns a null/empty string leave the String as default
  4. If the method returns a valid string set the String to this result

A Simple example would be:

    String temp = System.getProperty("XYZ");
    String result = "default";
    if(temp != null && !temp.isEmpty()){
        result = temp;
    }

I have made another attemp using a ternary operator:

    String temp;
    String result = isNotNullOrEmpty(temp = System.getProperty("XYZ")) ? temp : "default";

The isNotNullOrEmpty() Method

 private static boolean isNotNullOrEmpty(String str){
    return (str != null && !str.isEmpty());
}

Is it possible to do all of this in-line? I know I could do something like this:

String result = isNotNullOrEmpty(System.getProperty("XYZ")) ? System.getProperty("XYZ") : "default";

But I am calling the same method twice. I would be something like to do something like this (which doesn't work):

String result = isNotNullOrEmpty(String temp = System.getProperty("XYZ")) ? temp : "default";

I would like to initialize the 'temp' String within the same line. Is this possible? Or what should I be doing?

Thank you for your suggestions.

Tim

Cam1989
  • 1,241
  • 2
  • 9
  • 9

10 Answers10

118

If using JDK 9 +, use Objects.requireNonNullElse(T obj, T defaultObj)

AK4647
  • 1,371
  • 1
  • 10
  • 11
  • Great method, finally we got it. It's a shame it does not do automatic `int` to `long` casting. – kap Mar 10 '21 at 13:42
101

Use Java 8 Optional (no filter needed):

public static String orElse(String defaultValue) {
  return Optional.ofNullable(System.getProperty("property")).orElse(defaultValue);
}
Grigory Kislin
  • 16,647
  • 10
  • 125
  • 197
nobeh
  • 9,784
  • 10
  • 49
  • 66
  • 34
    WOW! Compared to swift's `s = q ?? r`. – Q8i May 09 '16 at 12:04
  • 37
    Optionals should not be created for flow control within a method. This is called out as an anti-pattern by the developers who built Optional. https://www.youtube.com/watch?amp=&v=Ej0sss6cq14 – Ryan Burbidge Jul 18 '19 at 21:56
  • 9
    @RyanBurbidge, and the reason: You unnecessarily create an object in your simple method (Optional object). – PAX Oct 09 '19 at 09:43
  • @PAX, if that's the only reason you can avoid it by using `Optional::orElseGet` instead. I personally prefer the ternary operator since it's just as lazy and shorter. – brunch875 Jan 28 '21 at 17:07
  • 1
    @RyanBurbidge, nice reference, thanks! Relevant part of the video: 27:44 - 30:00 – Pavel Feb 16 '21 at 07:08
  • 3
    @Q8i of course, if you make an operation unnecessarily complicated, you want to max it out. As otherwise, you could simply use `System.getProperty("property", defaultValue)` that does the job without additional syntactic constructs. – Holger Jun 07 '21 at 15:05
  • I don't know why this solution is so popular, it's quite verbose. – rendon Oct 29 '21 at 21:23
78

I know the question is really old, but with generics one can add a more generalized method with will work for all types.

public static <T> T getValueOrDefault(T value, T defaultValue) {
    return value == null ? defaultValue : value;
}
Grigory Kislin
  • 16,647
  • 10
  • 125
  • 197
Shibashis
  • 8,023
  • 3
  • 27
  • 38
  • Thanks shibashis. I still use this code and have a method for lots of object types! I will try with generics instead to simplify the code. Thank you – Cam1989 Jun 19 '17 at 16:33
  • 6
    @Cam1989: This doesn't answer the question you asked though, because it doesn't handle empty strings... it only deals with the value being `null`, not empty... if that's what you wanted, that's what you should have asked. This is a perfectly good solution to a different problem, but it *is* a solution to a different problem... – Jon Skeet Jun 20 '17 at 05:39
  • it would meet the empty requirement by replacing "value == null" with "isNotNullOrEmpty(value)" and switching value and defaultValue in the ternary responses – Steve Goossens Dec 12 '17 at 18:23
  • 1
    Careful! While the ternary operator itself is lazy, this solution isn't! Which means a call to `myThing = getValueOrDefault(thing, new Thing());` will create and discard that `new Thing()` if `thing` is not null. You may want to adapt this function to take a lambda instead so you may do `getValueOrDefault(thing, Thing::new)` instead. – brunch875 Jan 28 '21 at 17:04
  • 7
    @brunch875 Since Java 9, this functionality exist as standard API method: [`Objects.requireNonNullElse(T obj, T defaultObj)`](https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/Objects.html#requireNonNullElse(T,T)), including a variant with lazy construction of the fallback, [`Objects.requireNonNullElseGet(T obj, Supplier extends T> supplier)`](https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/Objects.html#requireNonNullElseGet(T,java.util.function.Supplier)). – Holger Jun 07 '21 at 15:17
65

Use org.apache.commons.lang3.StringUtils

String emptyString = new String();    
result = StringUtils.defaultIfEmpty(emptyString, "default");
System.out.println(result);

String nullString = null;
result = StringUtils.defaultIfEmpty(nullString, "default");
System.out.println(result);

Both of the above options will print:

default

default

Community
  • 1
  • 1
zalis
  • 1,191
  • 1
  • 11
  • 20
  • 3
    There is also `StringUtils.defaultIfBlank` to provide a default if the string is null or blank (e.g. contains spaces only) : `result = StringUtils.defaultIfBlank(emptyString, "default");`. – Pierre C Mar 11 '22 at 21:31
43

You can use this method in the ObjectUtils class from org.apache.commons.lang3 library :

public static <T> T defaultIfNull(T object, T defaultValue)
Tarik
  • 4,961
  • 3
  • 36
  • 67
  • This checks for `null`, but not for empty Strings. It's better to use `StringUtils.defaultIfBlank` instead – jmm Jun 18 '20 at 15:09
15

Sounds like you probably want a simple method like this:

public String getValueOrDefault(String value, String defaultValue) {
    return isNotNullOrEmpty(value) ? value : defaultValue;
}

Then:

String result = getValueOrDefault(System.getProperty("XYZ"), "default");

At this point, you don't need temp... you've effectively used the method parameter as a way of initializing the temporary variable.

If you really want temp and you don't want an extra method, you can do it in one statement, but I really wouldn't:

public class Test {
    public static void main(String[] args) {
        String temp, result = isNotNullOrEmpty(temp = System.getProperty("XYZ")) ? temp : "default";
        System.out.println("result: " + result);
        System.out.println("temp: " + temp);
    }

    private static boolean isNotNullOrEmpty(String str) {
        return str != null && !str.isEmpty();
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @fge Lets say it is not case of System.getProperty() but some method which doesn't have this extra parameter for default value. Then trick will work, it is scalable. – hagrawal7777 Jul 14 '15 at 16:50
  • How did I make this so complicated!? Thank you very much! I have used the getValueOrDefault() method. Great answer. – Cam1989 Jul 15 '15 at 07:56
2

With guava you can use

MoreObjects.firstNonNull(possiblyNullString, defaultValue);
lights
  • 1,034
  • 1
  • 8
  • 22
1

This is the best solution IMHO. It covers BOTH null and empty scenario, as is easy to understand when reading the code. All you need to know is that .getProperty returns a null when system prop is not set:

String DEFAULT_XYZ = System.getProperty("user.home") + "/xyz";
String PROP = Optional.ofNullable(System.getProperty("XYZ"))
        .filter(s -> !s.isEmpty())
        .orElse(DEFAULT_XYZ);
djangofan
  • 28,471
  • 61
  • 196
  • 289
1

If you need to set not null value or return default value instead you can use simple generic method

private <T> T getIfNotNullOrElse(T input, T defaultValue) {
   return Optional.ofNullable(input).orElse(defaultValue);
}
Daniel Hári
  • 7,254
  • 5
  • 39
  • 54
Andrii Chertok
  • 1,447
  • 1
  • 8
  • 9
0

In Java 9, if you have an object which has another object as property and that nested objects has a method yielding a string, then you can use this construct to return an empty string if the embeded object is null :

String label = Optional.ofNullable(org.getDiffusion()).map(Diffusion::getLabel).orElse("")

In this example :

  • org is an instance of an object of type Organism
  • Organism has a Diffusion property (another object)
  • Diffusion has a String label property (and getLabel() getter).

With this example, if org.getDiffusion() is not null, then it returns the getLabel property of its Diffusion object (this returns a String). Otherwise, it returns an empty string.

Pierre C
  • 2,920
  • 1
  • 35
  • 35