Option Type
null
in different clothes.
Use Optional<T>
to indicate when a value may not actually exist.
Example: Max value from a list of values.
Switch from:
Integer max = null;
for (int value: values) {
if (max == null) {
max = value;
} else if (max < value) {
max = value;
}
}
return max;
// Usage
int max = getMax(new int[] {}); // NullPointerException
to:
Optional<Integer> max = Optional.empty();
for (int value: values) {
max = max
.map(currentMax -> currentMax < value ? value : currentMax)
.orElse(value);
}
return max;
Example: Returning data from storage.
Switch from:
public interface DataStorage {
/**
* @return the data for the given ID, or null if it doesn't exist.
*/
public Data get(DataId dataId);
}
public class DataConsumer {
public void doSomething(DataId dataId) {
Data data = dataStorage.get(dataId);
if (data != null) {
// do something with it.
}
// `data` exists here, possible to use null reference.
}
}
to:
public interface DataStorage {
/**
* @return the data for the given ID if exists.
*/
public Optional<Data> get(DataId dataId);
}
public class DataConsumer {
public void doSomething(DataId dataId) {
dataStorage
.get(dataId)
.ifPresent(data -> {
// do something with it.
});
// `data` doesn't exist here, impossible to use null reference.
}
}
We communicate across the API boundary that the value may not exist.
Bug Variants Addressed
- 1: Use
Optional
to indicate when it is valid to not provide a value. - 3: Use
Optional
in return types to indicate there may not be a return value.