2

This might be a silly question.

When I am using Optional.isEmpty() like below in the code

Optional<List<String>> optional = Optional.of(new ArrayList<>());

optional.isEmpty(); // only checks if the value is NULL or not.

isEmpty() method is only checking whether the value null or not.

public boolean isEmpty() {
    return value == null;
}

This method name seems not clear for me.

I'm wondering why this method is named isEmpty() and not isNull() since it performs null-check under the hood?

  • According to the Java 8 [documentation](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html) there is no `isEmpty` method. Am I missing something? – Abra Sep 04 '22 at 08:25
  • You need to understand more what an Optional, it can holds a value or not. A null optional, is just like any object who would be null. A empty optional means it holds NO value, represented by a null value, seems very logical – azro Sep 04 '22 at 08:31
  • @Abra Yes, you're missing [Java 11](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html#isEmpty()). – khelwood Sep 04 '22 at 08:32
  • 1
    @khelwood did I misunderstand this part of the question: _I am using JDK 8_ ? – Abra Sep 04 '22 at 08:43
  • Sorry for giving misinformation. I am using java 11 and JDK 11. I don't know way i mentioned JDK 8 though. And i guess this question is not connected with specific java version. Sorry again. – YeonCheol Jang Sep 04 '22 at 12:07

4 Answers4

7

It’s the because the null check is an implementation detail, not what the method logically does. Logically, the method checks whether the optional value is empty or engaged.

Technically, this can be implemented in a number of ways, depending on how the Optional stores its value. JDK 8’s implementation happens to use a reference object with a null check, but other implementations could conceivably do this differently. It’s a mistake to confuse a high-level interface description with its implementation. The entire point of encapsulation is to abstract away implementation details from the user.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
3

You're missing the main point.

Optional is designed to be a container of data which can never be null by itself and which is safe to interact with.

Optional is not intended to be a substitution for null-checks. It's mean to represent a nullable return value and should not be creating in order to hide null-checks or chain methods on it (more on that, see here and here).

If you need to validate that something is not null you can use method Objects#requireNonNull() and it's flavors or explicit null-check.

The idea behind the optional, is that serves as a box for a value, and you can do whole lot of staff with it without caring if the box empty or not. Optional offers you methods to filter to the value inside the box filter(), to replace an empty box with another box or(), to transform the value inside the box map(), etc. And all these actions can be done by chaining the methods fluently without opening the box.

Methods isNull()/isNotNull() are not suitable for the Optional API because they contradict its design goal, which to provide a limited mechanism for representing a nullable return value and a mean of interaction with the target value (around which optional is wrapped) in a simple and fluent way regardless whether its value is null or not.

Note, that checks isPresent() (JDK 8) and isEmpty() (JDK 11) exist as a last resort. Be attentive when you're using them, because most likely you're not leveraging Optional to its full power.

Also, note that wrapping Optional around a Collection or an array doesn't make sense because they are container of data as well (like optional) and might be empty as well, which represents the absents of data.

Doing something like this is redundant and inconvenient.

Optional<List<String>> optional = Optional.of(new ArrayList<>());

When a collection is not null, which should be the case because keeping nullable collections is an antipattern, Collection.isEmpty() is sufficient to check if the data is present. Meanwhile, when you have optional wrapped around collection, the presence of collection inside the optional doesn't means that the actual data is exists.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
1

This is the definition of Optional:

A container object which may or may not contain a non-null value.

Since the object itself is a container, which may or may not hold a value, isEmpty (or isPresent) refers to the status of the container, whether it holds something or not.

isNull as a name would suggest that the Optional would be null, which would be a false impression, because the Optional itself is a properly existing instance.

Is the Optional null if it does not hold a not-null value? No, you can check for

myOptional == null

and you will see it's false (you couldn't even call isEmpty otherwise). Is the object inside the container null? If isEmpty is null, then it's a sure thing. Hence, the Optional is either empty, or something is present inside of it.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

Here's a different way of implementing Optional which checks emptiness by using different concrete classes for full and empty instances.

public interface MyOptional<T> {
    boolean isEmpty();
    T getOrDefault(T aDefault);

    static <T> MyOptional<T> empty() {
        return new MyOptional<T>() {
            @Override
            public boolean isEmpty() {
                return true;
            }

            @Override
            public T getOrDefault(T aDefault) {
                return aDefault;
            }
        };
    }

    static <T> MyOptional<T> of(T t) {
        return new MyOptional<T>() {
            @Override
            public boolean isEmpty() {
                return false;
            }

            @Override
            public T getOrDefault(T aDefault) {
                return t;
            }
        };
    }

    public static void main(String[] args) {
        MyOptional<String> optString = MyOptional.empty();

        System.out.println(optString.isEmpty());
    }
}

This has a semantic difference from Java's Optional: this can contain a null value in a full instance, while Java's cannot.

tgdavies
  • 10,307
  • 4
  • 35
  • 40