| 
 | 
	
 
前言 
 
NPE(NullPointerException)一直是Java程序员最深恶痛绝的异常,冗长的非空校验使代码的可读性和优雅性都大大降低。那么本篇文章,笔者将详细介绍一下Java 8 引入的特性--Optional类,看看它是如何避免空指针异常的。 
什么是Optional? 
 
Optional是一个容器对象,它可能包含或不包含非空值。如果存在值,isPresent()将返回true,而get()则返回该值。提供了取决于所包含值的存在与否的其他方法,例如orElse()(如果值不存在,则返回默认值)和ifPresent()(若值存在,则执行一段代码)。这是一个基于值的类;对Optional实例使用身份敏感操作(包括引用相等(==)、身份哈希码或同步)可能会产生不可预测的结果,应避免。 
Optional解决了什么问题? 
 
在 Java 8 之前,我们进行对象校验是这样的: 
 public String getCity(User user){ 
     if(user != null){ 
         Address address = user.getAddress(); 
         if(address != null){ 
             return address.getCity(); 
         }else{ 
             return "北京市"; 
         } 
     }else{ 
         return "北京市"; 
     } 
 } Java 8 写法: 
 public String getCity(User user){ 
     return Optional.ofNullable(user) 
         .map(u -> u.getAddress()) 
         .map(address -> address.getCity()) 
         .orElse("北京市"); 
  
 } 
方法详解 
 
empty 
 
描述 
 
返回空的 Optional 实例。 
源码 
 
 public static<T> Optional<T> empty() { 
     @SuppressWarnings(&#34;unchecked&#34;) 
     Optional<T> t = (Optional<T>) EMPTY; 
     return t; 
 }用法 
 
 Optional<Object> empty = Optional.empty();创建了一个空的Optional对象,如果此时调用get()方法,会抛出NoSuchElementException 
 Optional<Object> empty = Optional.empty(); 
 System.out.println(empty.get());// 抛出 NoSuchElementException 
of(T value) 
 
描述 
 
为非Null值创建一个Optional,传入参数不能为null,否则会抛出NullPointerException。 
源码 
 
 public static <T> Optional<T> of(T value) { 
     return new Optional<>(value); 
 }用法 
 
 Optional<String> userName = Optional.of(&#34;userName&#34;);如果传入null,则会抛出NullPointerException 
 Optional<String> userName = Optional.of(null);// 抛出 NullPointerException 
ofNullable(T value) 
 
描述 
 
创建可为空的Optional,如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。 
源码 
 
 public static <T> Optional<T> ofNullable(T value) { 
     return value == null ? empty() : of(value); 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
get()  
 
描述 
 
如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException。 
源码 
 
 public T get() { 
     if (value == null) { 
         throw new NoSuchElementException(&#34;No value present&#34;); 
     } 
     return value; 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
 System.out.println(userName.get());//输出 userName 
isPresent() 
 
描述 
 
如果存在值,则返回true,否则返回false。 
源码 
 
 public boolean isPresent() { 
     return value != null; 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
 System.out.println(userName.isPresent());//输出 true 
 Optional<String> empty = Optional.ofNullable(null); 
 System.out.println(empty.isPresent());//输出 false 
ifPresent(Consumer<? super T> consumer) 
 
描述 
 
如果值存在则使用该值调用 consumer , 否则不执行任何操作。 
要理解ifPresent方法,首先需要了解Consumer类。简答地说,Consumer类包含一个抽象方法。该抽象方法对传入的值进行处理,但没有返回值。Java8支持不用接口直接通过lambda表达式传入参数。 如果Optional实例有值,调用ifPresent()可以接受接口段或lambda表达式。 
源码 
 
 public void ifPresent(Consumer<? super T> consumer) { 
     if (value != null) 
         consumer.accept(value); 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
 userName.ifPresent((value) -> System.out.println(value.length()));//输出 8 
 Optional<String> empty = Optional.ofNullable(null); 
 empty.ifPresent((value) -> System.out.println(value.length()));//无输出,此时Optional为空值,不执行操作 
filter(Predicate<? super T> predicate) 
 
描述 
 
如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。 
源码 
 
 public Optional<T> filter(Predicate<? super T> predicate) { 
     Objects.requireNonNull(predicate); 
     if (!isPresent()) 
         return this; 
     else 
         return predicate.test(value) ? this : empty(); 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
 Optional<String> filterUserName1 = userName.filter((value) -> value.length() > 4); 
 System.out.println(filterUserName1.get());//输出 userName 
 Optional<String> filterUserName2 = userName.filter((value) -> value.length() < 4); 
 System.out.println(filterUserName2.get());//抛出 NoSuchElementException,因为此时没有找到匹配的值,返回一个空的Optional 
map(Function<? super T, ? extends U> mapper)  
 
描述 
 
如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。 
源码 
 
 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> userName = Optional.ofNullable(&#34;userName&#34;); 
 Optional<String> mapUserName = userName.map((value) -> value.toUpperCase(Locale.ROOT)); 
 System.out.println(mapUserName.get());//输出 USERNAME  
flatMap(Function<? super T, Optional<U>> mapper) 
 
描述 
 
如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional,此方法类似于map(Function),但提供的mapper的返回值必须是Optional,如果调用,flatMap不会用附加的Optional包装它。 
源码 
 
 public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) { 
     Objects.requireNonNull(mapper); 
     if (!isPresent()) 
         return empty(); 
     else { 
         return Objects.requireNonNull(mapper.apply(value)); 
     } 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
 Optional<String> flatMapUserName = userName.flatMap((value) -> 
                     Optional.of(value.toUpperCase(Locale.ROOT)) //mapper的返回值必须为Optional 
 ); 
 System.out.println(flatMapUserName.get());//输出 USERNAME 
orElse(T other) 
 
描述 
 
如果存在该值,返回值, 否则返回 other。 
源码 
 
 public T orElse(T other) { 
     return value != null ? value : other; 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
 System.out.println(userName.orElse(&#34;mobile&#34;));//输出 userName 
 Optional<Object> empty = Optional.empty(); 
 System.out.println(empty.orElse(&#34;mobile&#34;));//输出 mobile 
orElseGet(Supplier<? extends T> other) 
 
描述 
 
如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。 
源码 
 
 public T orElseGet(Supplier<? extends T> other) { 
     return value != null ? value : other.get(); 
 }用法 
 
 Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
 System.out.println(userName.orElseGet(() -> &#34;mobile&#34;));//输出 userName 
 Optional<Object> empty = Optional.empty(); 
 System.out.println(empty.orElseGet(() -> &#34;mobile&#34;));//输出 mobile 
orElseThrow(Supplier<? extends X> exceptionSupplier) 
 
描述 
 
如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常 
源码 
 
 public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { 
     if (value != null) { 
         return value; 
     } else { 
         throw exceptionSupplier.get(); 
     } 
 }用法 
 
 try { 
     Optional<String> userName = Optional.ofNullable(&#34;userName&#34;); 
     System.out.println(userName.orElseThrow(Exception::new));//输出 userName 
 } catch (Exception e) { 
     e.printStackTrace(); 
 } 
 try { 
     Optional<Object> empty = Optional.empty(); 
     System.out.println(empty.orElseThrow(Exception::new)); 
 } catch (Exception e) { 
     e.printStackTrace(); //异常捕获 
 } 
总结 
 
以上便是Optional的各个方法的用法介绍,还是建议大家熟练使用,这样能让自己的代码变得更加优雅。 |   
 
 
 
 |