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);