错误用法:
1、先使用isPresent来判断是否有值,然后使用get()方法取出元素。
Optional<String> optional = Optional.empty();
if (optional.isPresent()) {
String str = optional.get();
}
public boolean isPresent() {
return value != null;
}
说明:我直接用!Objects.isNull()判断下,再处理它不香吗?为什么还要用这个Optional呢?
2、使用Optional作为方法参数来使用
void badMethod(Optional<String> optional) {
...;
}
说明:每个方法都应该对参数进行合法性校验的,除非是内部使用的private方法,我们确定参数的取值情况时可以不进行校验。这个方法的参数意思就是说:我会判断是否为空的(用的错误方法1),你们放心传给我参数就好了。这不是废话?
3、使用Optional来作为类的成员属性
public class BadClass {
private Optional<String> optional;
...
}
说明: 类的成员属性,对象类型的默认值本来就是null的,你搞一个Optional来当成员属性是几个意思??难道是:“大家好!我这个类的属性是可能为null的,我考虑很周到的,我代码逼格很高的”。我表示很无语,因为真的有“前辈”这么用的!
正确用法:
定义方法的返回值的类型为Optional,因为方法的返回值可能为空,也可能有值的。根据返回值的情况,有选择性的处理相应的逻辑。这里我把“有选择性的”标记了,因为这个就是Optional的中文意思,也是它的用法所代表的意思。
两个成员属性:封装的值、空Optional对象
/*空Optional对象*/
private static final Optional<?> EMPTY = new Optional<>();
/*封装的值*/
private final T value;
empty方法的使用:返回的就是静态的成员属性EMPTY
public static<T> Optional<T> empty() {
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
先看下创建Optional对象的两个方式:(这个不是重点)
1、Optional.of():
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
说明:可以看到如果传一个null给of方法的话,会直接抛一个空指针异常,还有一个是optional.get()方法,如果value为空的话,也是直接抛异常的。说明人家作者根本不是说要用Optional来防止NullPointerException异常的发生的,而是用一种有选择性的简洁的方式去处理一个可能为空的对象,不知道怎么就被误认为了用Optional就没有空指针异常的问题了。
2、Optional.ofNullable():
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
这个方法是可以传入null值的,不会抛出空指针异常。
下面围绕这个“有选择性的”展开介绍:
1、针对一个可能为空的对象,如果有值的话就选择处理这个值,使用ifPresent(Consumer)
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
说明:如果value值不为空的话,消费这个值(也就是处理这个值)
用法:
Optional<String> optional = Optional.of("river66");
optional.ifPresent(System.out::println);
关于Consumer的使用,可以参考下:https://blog.youkuaiyun.com/river66/article/details/108178965
2、针对一个可能为空的对象,如果不符合给定的条件,则作为空处理,使用filter(Predicate)
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
关于Predicate的用法,可以参考下:https://blog.youkuaiyun.com/river66/article/details/107028467
用法:
Optional<String> optional = Optional.of("");
optional = optional.filter(""::equals);
3、针对一个可能为空的对象,只要不是null值,就转化为另一个值,使用map(Function)
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
用法:
Optional<String> optional = Optional.of("123");
Optional<Integer> op = optional.filter((a)->{
boolean b;
try {
Integer.parseInt(a);
b = true;
} catch (NumberFormatException e) {
b = false;
}
return b;
}).map(Integer::parseInt);
说明:如果filter中返回的是false,则意味着value将为null,但是map中调用的是ofNullable,所以map是可以跟在filter后使用的。而flatMap这个方式是不可以跟在filter后面的,因为会抛出NullPointerException。
关于Function的用法,可以参考下:https://blog.youkuaiyun.com/river66/article/details/108545027
4、针对一个可能为空的对象,不为空则返回value,为空则返回给定的默认值,使用T orElse(T other)
public T orElse(T other) {
return value != null ? value : other;
}
用法:
Optional<String> optional = Optional.empty();
String notNull = optional.orElse("");
5、针对一个可能为空的对象,不为空则返回value,为空则返回给定的默认值(Lambda表达式返回的值,即Supplier),使用orElseGet(Supplier)。
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
用法:
Optional<String> optional = Optional.empty();
String notNull = optional.orElseGet(()->{return "";});
6、针对一个可能为空的对象,不为空则返回value,为空就抛异常,使用orElseThrow(Supplier) throws X
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
用法:
Optional<String> optional = Optional.empty();
String a = optional.orElseThrow(() -> new NoSuchElementException(""));
本文探讨了Java Optional类的误用和正确使用方式。常见错误包括使用isPresent后再get(),作为方法参数和成员属性。正确用法在于作为方法返回值类型,以有选择性地处理可能为空的对象。Optional提供的方法如ifPresent、filter、map、orElse等提供了处理空值的优雅方式,避免直接抛出NullPointerException。
5万+

被折叠的 条评论
为什么被折叠?



