前言
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("unchecked") 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("userName");
如果传入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("userName");
get()
形容
如果在这个Optional中蕴含这个值,返回值,否则抛出异样:NoSuchElementException。
源码
public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value;}
用法
Optional<String> userName = Optional.ofNullable("userName");System.out.println(userName.get());//输入 userName
isPresent()
形容
如果存在值,则返回true,否则返回false。
源码
public boolean isPresent() { return value != null;}
用法
Optional<String> userName = Optional.ofNullable("userName");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("userName");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("userName");Optional<String> filterUserName1 = userName.filter((value) -> value.length() > 4);System.out.println(filterUserName1.get());//输入 userNameOptional<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("userName");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("userName");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("userName");System.out.println(userName.orElse("mobile"));//输入 userName
Optional<Object> empty = Optional.empty();System.out.println(empty.orElse("mobile"));//输入 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("userName");System.out.println(userName.orElseGet(() -> "mobile"));//输入 userName
Optional<Object> empty = Optional.empty();System.out.println(empty.orElseGet(() -> "mobile"));//输入 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("userName"); 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的各个办法的用法介绍,还是倡议大家纯熟应用,这样能让本人的代码变得更加优雅。