Optional<T>是对一个T对象的封装,如果存在被封装的对象,那么get()方法会返回改对象,否则会抛出NoSuchElementException。
创建Optional<T>
// Create an empty Optional. Optional<Object> empty = Optional.empty(); // Create with given element. Optional<Session> session = Optional.of(new Session()); Optional<Session> session = Optional.of(aNullableSession);
使用Optinal.of(obj)时,传入的对象,不能是null,否则会抛出NullPointerException。如Optional.of(null),是错误的。
通常情况下,不确定传入的对象是否为null。此时应当用Optional.ofNullable(obj),如果obj不是null,返回封装obj的Optional对象;否则返回Optional.empty()。
普通使用Optional
直接调用get()方法返回的对象,对代码没有任何改进。
RunJob job = ... job.run(); //Havn't improved than old usage. Optional<RunJob> optionalJob = ... optionalJob.get().run();
Optional的isPresent()方法可以判断封装对象是否存在,但是这个并没有简化code。
if (value != null) {
value.someMethod();
}
// No much difference than above usage.
if (optionalValue.isPresent()) {
optionalValue.get().someMethod();
}
正确高效得使用Optional
ifPresent(Consumer): void
当对象存在的时候,执行一段代码,没有返回值。
Optional<RecalculateSession> recalculate = null;
recalculate.ifPresent(r -> {
checkFolder();
clearResult();
r.run();
});
map(Function<? super T, ? extends U>): Optional<U>
当对象存在的时候,执行一段代码,并返回一个值,该返回值被自动封装在Optional。如果返回的是null,则返回Optional.empty()。
Optional<RecalculateSession> recalculate = null;
Optional<Boolean> result = recalculate.map(r -> {
try {
r.run();
return true;
} catch (Exception e) {
Logger.logMsg(Logger.INFO, "Recalculate failed");
return false;
}
});
flatMap(Function<? super T, Optional<U>>): Optional<U>
当对象存在的时候,执行一段代码,返回一个Optional对象。区别:map()的Lambda表达式,返回的是普通变量。flatMap()的表达式,返回的是Optional对象。
Optional<String> word = Optional.of("melodrama");
//Optional<Integer> length = word.map(w -> w.length());
Optional<Integer> length = word.flatMap(w -> Optional.of(w.length()));
orElse(T): T
当对象不存在时,返回一个默认值。
Optional<String> sessionDir = Optional.empty();
String thePath = sessionDir.orElse("A default path");
orElseGet(Supplier): T
当对象不存在时,执行一段代码,返回一个默认值。
Optional<String> sessionDir = Optional.empty();
String thePath = sessionDir.orElseGet(() -> {
if (isVisualizationSession()) {
return "Visualization default session";
} else {
return "Generic default session";
}
});
orElseThrow(Supplier): Throwable
当对象不存在时,执行一段代码,返回一个Exception。
Optional<String> sessionDir = Optional.empty();
String thePath = sessionDir.orElseThrow(() -> {
releaseResources();
return new NoSuchElementException();
});
Example: 连续调用,不产生NullPointerException
class SessionUtil {
public static Session getSession(int id) {…};
public static SessionInfo getSessionInfo(Session session) {…};
public static String getDescription(SessionInfo info) {…};
}
场景:给定Session Id,要获得该session的description。Java8之前的做法:
int id = 99;
Session session = SessionUtil.getSession(id);
if (session != null) {
SessionInfo sessionInfo = SessionUtil.getSessionInfo(session);
if (sessionInfo != null) {
String description = SessionUtil.getDescription(sessionInfo);
if (description != null) {
System.out.println(description);
}
}
}
Java8中使用Optional的map方法,不用null check。只有每步都有返回值时,最后才会打印出来description。
Optional<Integer> sessionId = Optional.of(99);
sessionId.map(SessionUtil::getSession)
.map(SessionUtil::getSessionInfo)
.map(SessionUtil::getDescription)
.ifPresent(System.out::println);
如果上述SessionUtil的返回值,都是用Optional封装的,就使用flatMap()方法。
class SessionUtil {
public static Optional<Session> getSession(int id) {...};
public static Optional<SessionInfo> getSessionInfo(Session session) {...};
public static Optional<String> getDescription(SessionInfo info) {...};
}
Optional<Integer> sessionId = Optional.of(99);
sessionId.flatMap(SessionUtil::getSession)
.flatMap(SessionUtil::getSessionInfo)
.flatMap(SessionUtil::getDescription)
.ifPresent(System.out::println);