1.Optional作用
Optional类JDK8开始引入的,为的是能够更加优雅地处理NullPointerException,优雅地判空和处理空值。Optional对象是一种包装器对象,包装了类型T的对象或者是没有包装任何对象。若是包装了类型T的对象可以认为值是存在的。Optional类以更安全的方式代替了类型T的引用,这种引用要么就是引用某个对象,要么为null。
2.Optional的创建
使用 Optional.of 、Optional.ofNullable 或 Optional.empty
- Optional.of(object): 创建一个非空的包装对象,若object为null就会报出异常(NPE);
- Optional.empty(): 创建一个空的optional对象。
- Optional.ofNullable(object): 该方法为一种兼容的方法,若objcet不为null,它就和Optional.of()方法一样。若是object为null时,就创建一个空的optional对象。
源码
/**
* Returns an empty {@code Optional} instance. No value is present for this
* {@code Optional}.
*
* @apiNote
* Though it may be tempting to do so, avoid testing if an object is empty
* by comparing with {@code ==} against instances returned by
* {@code Optional.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @param <T> The type of the non-existent value
* @return an empty {@code Optional}
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
/**
* Returns an {@code Optional} describing the given non-{@code null}
* value.
*
* @param value the value to describe, which must be non-{@code null}
* @param <T> the type of the value
* @return an {@code Optional} with the value present
* @throws NullPointerException if value is {@code null}
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
* Returns an {@code Optional} describing the given value, if
* non-{@code null}, otherwise returns an empty {@code Optional}.
*
* @param value the possibly-{@code null} value to describe
* @param <T> the type of the value
* @return an {@code Optional} with a present value if the specified value
* is non-{@code null}, otherwise an empty {@code Optional}
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
创建案例
Optional.of(object)
Optional<String> op1 = Optional.e(null);
//op1会报异常 NullPointerExcetion
String user = "abc";
Optional<String> op2 = Optional.of(user);
//op2 创建实例
Optional.empty()
Optional<String> op1 = Optional.empty();
// 创建一个为空的Optional实例
Optional.ofNullalbe(objcet)
//下面创建了一个不包含任何值的Optional实例
//例如,值为'null'
Optional<String> op1 = Optional.ofNullalbe(null);
3.Optional的方法
isPresent
作用: 如果值存在返回true,否则返回false。
源码:
/**
* If a value is present, returns {@code true}, otherwise {@code false}.
*
* @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
案例:
Optional<String> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
System.out.println("op1: "+ op1.isPresent());//false
System.out.println("op2: "+ op2.isPresent());//true
get
作用: 如果Optional对象存在值则返回该值,否则抛出异常NoSuchElementException。
源码:
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @apiNote
* The preferred alternative to this method is {@link #orElseThrow()}.
*
* @return the non-{@code null} value described by this {@code Optional}
* @throws NoSuchElementException if no value is present
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
案例:
String user = "abc";
Optional<String> op = Optional.of(user);
System.out.println(op.get());//abc
ifPresent
作用: Optional实例有值存在则为其调用Consumer,否则不做处理。
源码:
/**
* If a value is present, performs the given action with the value,
* otherwise does nothing.
*
* @param action the action to be performed, if a value is present
* @throws NullPointerException if value is present and the given action is
* {@code null}
*/
public void ifPresent(Consumer<? super T> action) {
if (value != null) {
action.accept(value);
}
}
案例:
Optional<String> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
op1.ifPresent((value)->{
System.out.println("op1:"+value);
});//不显示
op2.ifPresent((value)->{
System.out.println("op2:"+value);
});//op2:abc
orElse
作用: 如果有值则返回,否则将返回指定的值。
源码:
/**
* If a value is present, returns the value, otherwise returns
* {@code other}.
*
* @param other the value to be returned, if no value is present.
* May be {@code null}.
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
案例:
Optional<String> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
System.out.println("op1:"+op1.orElse("op1op1"));//op1:op1op1
System.out.println("op2:"+op2.orElse("op2op2"));//op2:abc
orElseGet
作用: orElseGet和orElse类似,区别是orElse传入的是默认值,orElseGet是lambda表达式生成默认值。
源码:
/**
* If a value is present, returns the value, otherwise returns the result
* produced by the supplying function.
*
* @param supplier the supplying function that produces a value to be returned
* @return the value, if present, otherwise the result produced by the
* supplying function
* @throws NullPointerException if no value is present and the supplying
* function is {@code null}
*/
public T orElseGet(Supplier<? extends T> supplier) {
return value != null ? value : supplier.get();
}
案例:
Optional<String> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
System.out.println(op1.orElseGet(() -> "op1op1"));//op1op1
System.out.println(op2.orElseGet(() -> "op2op2"));//abc
orElseThrow
作用: 若有值则返回,否则抛出异常NoSuchElementException。
源码:
/**
* If a value is present, returns the value, otherwise throws
* {@code NoSuchElementException}.
*
* @return the non-{@code null} value described by this {@code Optional}
* @throws NoSuchElementException if no value is present
* @since 10
*/
public T orElseThrow() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
案例:
Optional<String> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
System.out.println(op1.orElseThrow());//抛出异常 NoSuchElementException: No value present
System.out.println(op2.orElseThrow());//abc
map
作用: 若存在值,则执行调用mapping函数得到返回值,若为null则返回为空的Optional。
源码:
/**
* If a value is present, returns an {@code Optional} describing (as if by
* {@link #ofNullable}) the result of applying the given mapping function to
* the value, otherwise returns an empty {@code Optional}.
*
* <p>If the mapping function returns a {@code null} result then this method
* returns an empty {@code Optional}.
*
* @apiNote
* This method supports post-processing on {@code Optional} values, without
* the need to explicitly check for a return status. For example, the
* following code traverses a stream of URIs, selects one that has not
* yet been processed, and creates a path from that URI, returning
* an {@code Optional<Path>}:
*
* <pre>{@code
* Optional<Path> p =
* uris.stream().filter(uri -> !isProcessedYet(uri))
* .findFirst()
* .map(Paths::get);
* }</pre>
*
* Here, {@code findFirst} returns an {@code Optional<URI>}, and then
* {@code map} returns an {@code Optional<Path>} for the desired
* URI if one exists.
*
* @param mapper the mapping function to apply to a value, if present
* @param <U> The type of the value returned from the mapping function
* @return an {@code Optional} describing the result of applying a mapping
* function to the value of this {@code Optional}, if a value is
* present, otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is {@code null}
*/
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> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
Optional<String> Cop1 = op1.map((values) -> values.toUpperCase());
Optional<String> Cop2 = op2.map((values) -> values.toUpperCase());
System.out.println(Cop1);//Optional.empty
System.out.println(Cop2);//Optional[ABC]
flatMap
作用: flatMap方法与map方法相似,区别再mapping函数的返回值不同。flatMap的mapper返回值必须为Optional类型返回值。
源码:
/**
* If a value is present, returns the result of applying the given
* {@code Optional}-bearing mapping function to the value, otherwise returns
* an empty {@code Optional}.
*
* <p>This method is similar to {@link #map(Function)}, but the mapping
* function is one whose result is already an {@code Optional}, and if
* invoked, {@code flatMap} does not wrap it within an additional
* {@code Optional}.
*
* @param <U> The type of value of the {@code Optional} returned by the
* mapping function
* @param mapper the mapping function to apply to a value, if present
* @return the result of applying an {@code Optional}-bearing mapping
* function to the value of this {@code Optional}, if a value is
* present, otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is {@code null} or
* returns a {@code null} result
*/
public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent()) {
return empty();
} else {
@SuppressWarnings("unchecked")
Optional<U> r = (Optional<U>) mapper.apply(value);
return Objects.requireNonNull(r);
}
}
案例:
Optional<String> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
Optional<String> Cop1 = op1.flatMap((value) -> Optional.of(value.toUpperCase()));
Optional<String> Cop2 = op2.flatMap((value) -> Optional.of(value.toUpperCase()));
System.out.println(Cop1);//Optional.empty
System.out.println(Cop2);//Optional[ABC]
filter
作用: filter为通过传入限定条件对Optional实例的值进行过滤。有值返回过滤后的值,否则返回空Optional。
源码:
/**
* If a value is present, and the value matches the given predicate,
* returns an {@code Optional} describing the value, otherwise returns an
* empty {@code Optional}.
*
* @param predicate the predicate to apply to a value, if present
* @return an {@code Optional} describing the value of this
* {@code Optional}, if a value is present and the value matches the
* given predicate, otherwise an empty {@code Optional}
* @throws NullPointerException if the predicate is {@code null}
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent()) {
return this;
} else {
return predicate.test(value) ? this : empty();
}
}
案例:
Optional<String> op1 = Optional.empty();
String user = "abc";
Optional<String> op2 = Optional.of(user);
Optional<String> longName = op2.filter((value) -> value.length() > 2);
System.out.println(longName.orElse("less"));//abc
Optional<String> shortName = op1.filter((value) -> value.length() > 2);
System.out.println(shortName.orElse("less"));//less