Java8中的多个 null 检查

我有下面的代码,这是有点丑陋的多个空检查。

String s = null;


if (str1 != null) {
s = str1;
} else if (str2 != null) {
s = str2;
} else if (str3 != null) {
s = str3;
} else {
s = str4;
}

因此,我尝试使用 Optional.ofNullable,如下,但它仍然很难理解,如果有人读我的代码。在 Java8中实现这一点的最佳方法是什么。

String s = Optional.ofNullable(str1)
.orElse(Optional.ofNullable(str2)
.orElse(Optional.ofNullable(str3)
.orElse(str4)));

在 Java9中,我们可以使用 Optional.ofNullableOR,但是在 Java8中有其他的方法吗?

16073 次浏览

How about ternary conditional operator?

String s =
str1 != null ? str1 :
str2 != null ? str2 :
str3 != null ? str3 : str4
;

You may do it like so:

String s = Stream.of(str1, str2, str3)
.filter(Objects::nonNull)
.findFirst()
.orElse(str4);

You can also use a loop:

String[] strings = {str1, str2, str3, str4};
for(String str : strings) {
s = str;
if(s != null) break;
}

A solution which can be applied to as many element as you want can be :

Stream.of(str1, str2, str3, str4)
.filter(Object::nonNull)
.findFirst()
.orElseThrow(IllegalArgumentException::new)

You could imagine a solution like below, but the first one ensures non nullity for all of the elements

Stream.of(str1, str2, str3).....orElse(str4)

You can also lump up all the Strings into an array of String then do a for loop to check and break from the loop once it's assigned. Assuming s1, s2, s3, s4 are all Strings.

String[] arrayOfStrings = {s1, s2, s3};




s = s4;


for (String value : arrayOfStrings) {
if (value != null) {
s = value;
break;
}
}

Edited to throw in condition for default to s4 if none is assigned.

Current answers are nice but you really should put that in a utility method:

public static Optional<String> firstNonNull(String... strings) {
return Arrays.stream(strings)
.filter(Objects::nonNull)
.findFirst();
}

That method has been in my Util class for years, makes code much cleaner:

String s = firstNonNull(str1, str2, str3).orElse(str4);

You can even make it generic:

@SafeVarargs
public static <T> Optional<T> firstNonNull(T... objects) {
return Arrays.stream(objects)
.filter(Objects::nonNull)
.findFirst();
}


// Use
Student student = firstNonNull(student1, student2, student3).orElseGet(Student::new);

I use a helper function, something like

T firstNonNull<T>(T v0, T... vs) {
if(v0 != null)
return v0;
for(T x : vs) {
if (x != null)
return x;
}
return null;
}

Then this kind of code can be written as

String s = firstNonNull(str1, str2, str3, str4);

Method based and simple.

String getNonNull(String def, String ...strings) {
for(int i=0; i<strings.length; i++)
if(strings[i] != null)
return s[i];
return def;
}

And use it as:

String s = getNonNull(str4, str1, str2, str3);

It's simple to do with arrays and looks pretty.

If you use Apache Commons Lang 3 then it can be written like this:

String s = ObjectUtils.firstNonNull(str1, str2, str3, str4);

Use of ObjectUtils.firstNonNull(T...) was taken from this answer. Different approaches were also presented in related question.

Using of a for loop will be the most suitable solution, as all beginner and experienced developers have enough knowledge of Loops. It's quite simple, first make an array, and then check the entries one by one. If any nonNull string found then stop the loop, and proceed to the results.

String[] myData = {s1, s2, s3, s4};
String s = null;


for (String temp : myData) {
if (temp != null) {
s = temp;
break;
}
}

Now you can track the nonNull value of the string, or can check if all strings were null, by using the below code.

if(s != null)
System.out.println(s);
else
System.out.println("All Strings are null");