Null / empty string judgment 2.0 using Optional

After all, if I use an if statement, I thought it would be better not to use Optional at all. I want to evolve null / empty string judgment with Optional.

Unless otherwise noted, it is assumed to work with Java 1.8 or higher.

Trigger

Recently, I found something like this in the code that performs "existence check" of a character string, and it made me feel quite uncomfortable: thinking:

String uri = SystemPropertiesUtil.getPropertyOptional(Constant.URI).orElse("");

if (StringUtils.isEmpty(dkInfoGetApiUrl)) {
//If it's null, I'll do something
}

This is a scene where you get the API URI from the DB and use it for the API call. getPropertyOptional is a method that returns Optional. Also, StringUtils # isEmpty that appears in the if statement is a utility method provided by the Spring Framework.

In this case, you can usually judge null / empty string, and it is rather simple to not use Optional.

This example is a bit extreme, but we will consider whether it is possible to improve usability and safety by using Optional for the general "non-null ∧ not empty string".

The nature of Optional

Optional is according to Javadoc

A container object that may or may not contain non-null values.

There is (Optional (Java Platform SE 8)).

If null does not appear at the time of wrapping with Optional # ofNullabele, the value can be obtained as it is, otherwise it can be processed separately. In other words, there is not much reason to return an empty string.

However, if you want to check both that the String instance is not null and that it is not an empty string, keep in mind that if you initialize it with Optional # ofNullable, it will be unchecked that it is not an empty string.

solution

Generally, when judging an empty string

--null check --Empty string check

I think that there are many cases where the static method that returns boolean is used to judge. For example

StringUtil.java


public static boolean isNullOrEmpty(String string) {
    if (string == null || string.equals("")) return true;

    return false;
}

Can it be replaced as follows? If you want to confirm that the expected character string is included in Optional, try adding the following method to the common StringUtils.

StringUtil.java


public static Optional<String> ofPresentable(String string) {
    if (string == null || string.equals("")) return Optional.empty();

    return Optional.of(string);
}

2020-11-17: Addendum I'm glad I got another idea in the comment, so I added it.

StringUtil.java


public static Optional<String> ofPresentable(String string) {
    return Optional.ofNullable(string).filter(s -> !s.isEmpty());
    //IsBlank can be used with Java 11 or above
    // return Optional.ofNullable(string).filter(String::isBlank);
}

By wrapping the return value with Optional, it is possible to specify the possibility that the value does not exist. Therefore, until now

SomeObject object = new SomeObject();
if(id == null || id.equals("")) {
    object.setId("default");
} else {
    object.setId(id);
}

Where I was

final String idPresentable = StringUtil.ofPresentable(id).orElse("default");
SomeObject object = new SomeObject(idPresentable);

Can be done. To be honest, there is no big difference in what you are doing, but by eliminating the control syntax, you can reduce the load of paying attention to state changes, making it easier to follow and change. In addition, since the possibility of becoming null can be specified, it is possible to prevent an unexpected error by throwing an arbitrary run-time exception in a place where it cannot be null in logic.

In other words

final String idPresentable = StringUtil.ofPresentable(id).orElseThrow(new RuntimeException("Unexpected input"));
SomeObject object = new SomeObject(idPresentable);

It's not 100% alternative, and there may be use cases that aren't suitable. However, I feel that this pattern is more effective in some cases, and I would definitely like to try it in the future.

bonus

This time, I felt a strong problem in the processing of character strings, but by preparing similar methods for List and Map, it seems that element existence judgment and processing in some cases can be done simply and safely.

For example

ListUtil.java


public static <T> Optional<List<T>> ofPresentable(List<T> list) {
    if (list == null || list.size() == 0) return Optional.empty();

    return Optional.of(list);
}

If you want to make it rich, you may also determine if the list element contains null.

Recommended Posts

Null / empty string judgment 2.0 using Optional
Null, empty string, blank
Difference between element 0, null and empty string (check in list)
StringUtils.isNotBlank is convenient for empty judgment and null judgment in java