空指针异常是我们在实际开发中经常会遇到的问题,为了防止程序因为异常而中断,通常要在代码中添加大量的非空验证,例如一个释放 JDBC 相关资源的代码,如下所示。

public static void release(Connection conn,Statement stmt,ResultSet rs) { try { if(conn != null) { conn.close(); } if(stmt != null) { stmt.close(); } if(rs != null) { rs.close(); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }}

上述代码中的非空验证并没有多少技术含量,同时会使代码显得臃肿不堪,为了解决这类问题,Java8 引入了 Optional 类,Optional 就是一个容器,它可以保存任意数据类型的值,包括 null,开发者无需进行空值检测,Optional 类的引入很好的解决了实际开发中的空指针异常问题,接下来我们来详细学习 Optional 类的使用。

Optional 常用方法

1、empty(),返回一个空的 Optional 对象,定义如下所示。

public static Optional empty() { @SuppressWarnings("unchecked") Optional t = (Optional) EMPTY; return t;}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.empty(); System.out.println(optional); }}

运行结果如下图所示。

2、of(T value),根据传入的 value 创建一个 Optional 对象,定义如下所示。

public static  Optional of(T value) { return new Optional<>(value);}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.of("Hello World"); System.out.println(optional); }}

运行结果如下图所示。

可以看到输出的结果是 Optional[Hello World],如果要取出 Hello World 直接调用 get 方法即可,如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.of("Hello World"); System.out.println(optional.get()); }}

但是需要注意的是,of 方法不能传 null,否则会抛出空指针异常,如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.of(null); System.out.println(optional); }}

3、ofNullable(T value),和 of(T value) 方法类似,都是用来创建 Optional 对象的,区别在于 ofNullable(T value) 方法可以传 null,定义如下所示。

public static  Optional ofNullable(T value) { return value == null ? empty() : of(value);}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable(null); System.out.println(optional); }}

运行结果如下图所示。

4、get(),返回 Optional 中存储的任意类型值,如果 Optional 中的值为 null,则抛出 java.util.NoSuchElementException,定义如下所示。

public T get() { if (value == null) { throw new NoSuchElementException("No value present"); } return value;}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable("Hello World"); System.out.println(optional.get()); optional = Optional.ofNullable(100); System.out.println(optional.get()); Integer[] array = {1,2,3,4,5,6}; optional = Optional.ofNullable(array); System.out.println(optional.get()); }}

运行结果如下图所示。

如果是下面这种情况,直接抛出 java.util.NoSuchElementException 异常。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable(null); System.out.println(optional.get()); }}

5、isPresent(),判断 Optional 存储的值是否存在,返回 true 表示有值,false 表示值不存在,定义如下所示。

public boolean isPresent() { return value != null;}

具体使用如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable("Hello World"); System.out.println(optional.isPresent()); optional = Optional.ofNullable(null); System.out.println(optional.isPresent()); }}

运行结果如下图所示。

6、ifPresent(Consumer super T> consumer),如果值存在,执行 Consumer 的具体操作,如果值不存在,不做任何操作,定义如下所示。

public void ifPresent(Consumer super T> action) { if (value != null) { action.accept(value); }}

具体操作如下所示。

public class Test { public static void main(String[] args) { //值存在 List list = Arrays.asList(1,2,3,4,5,6); Optional optional = Optional.ofNullable(list); System.out.print("值存在:"); optional.ifPresent(System.out::println); //值不存在 optional = Optional.ofNullable(null); System.out.print("值不存在:"); optional.ifPresent((str)-> System.out.println(str)); }}

运行结果如下图所示。

7、ifPresentOrElse(Consumer super T> action, Runnable emptyAction),如果值存在,执行 Consumer 的具体操作,如果值不存在,执行 emptyAction 的具体操作,定义如下所示。

public void ifPresentOrElse(Consumer super T> action, Runnable emptyAction) { if (value != null) { action.accept(value); } else { emptyAction.run(); }}

具体操作如下所示。

public class Test { public static void main(String[] args) { //值存在 List list = Arrays.asList(1,2,3,4,5,6); Optional optional = Optional.ofNullable(list); System.out.print("值存在:"); optional.ifPresentOrElse(System.out::println,()-> System.out.println("value is null")); //值不存在 optional = Optional.ofNullable(null); System.out.print("值不存在:"); optional.ifPresentOrElse(System.out::println,()-> System.out.println("value is null")); }}

运行结果如下图所示。

8、filter(Predicate super T> predicate),根据传入的 Predicate 对 Optional 中的值进行过滤,满足条件则返回该 Optional 对象,否则返回一个空的 Optional,定义如下所示。

public Optional filter(Predicate super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) { return this; } else { return predicate.test(value) ? this : empty(); }}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable(1); Predicate predicate = num -> num >= 3; System.out.println(optional.filter(predicate)); predicate = num -> num < 3; System.out.println(optional.filter(predicate)); }}

运行结果如下图所示。

9、map(Function super T, ? extends U> mapper),如果 Optional 有值,则执行 mapper 映射函数,并获取其返回值,如果返回值不为 null,则返回一个包含返回值的 Optional 对象,否则返回一个空的 Optional 对象,定义如下所示。

public Optional map(Function super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) { return empty(); } else { return Optional.ofNullable(mapper.apply(value)); }}

具体操作如下所示。

public class Test { public static void main(String[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA.setClassB(classB); Optional optional = Optional.ofNullable(classA) .map((classA1)->classA1.getClassB()); System.out.println(optional); }}class ClassA { private ClassB classB; public ClassB getClassB() { return classB; } public void setClassB(ClassB classB) { this.classB = classB; }}class ClassB {}

上述代码表示如果 classA 中包含 classB,则直接返回一个 Optional[ClassB] 对象,否则返回一个空的 Optional 对象,运行结果如下图所示。

对上述代码进行修改,删除 classA.setClassB(classB); 如下所示。

ClassB classB = new ClassB();ClassA classA = new ClassA();Optional optional = Optional.ofNullable(classA) .map((classA1)->classA1.getClassB());System.out.println(optional);

运行结果如下图所示。

这里需要注意的是 map 方法的调用必须和 Optional 的创建连起来写,如下所示。

Optional optional = Optional.ofNullable(classA).map((classA1)->classA1.getClassB());

不能分开写,错误写法如下所示。

Optional optional = Optional.ofNullable(classA);optional.map((classA1)->classA1.getClassB());

10、flatMap(Function super T, ? extends Optional extends U>> mapper),功能与 map 类似,区别在于 map 的 mapper 映射函数可返回任意数据类型,但是 flatMap 的 mapper 映射函数只能返回 Optional 类型,定义如下所示。

public Optional flatMap(Function super T, ? extends Optional extends U>> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) { return empty(); } else { @SuppressWarnings("unchecked") Optionalr = (Optional) mapper.apply(value); return Objects.requireNonNull(r); }}

具体操作如下所示。

public class Test { public static void main(String[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA.setClassB(classB); Optional optional = Optional.ofNullable(classA) .flatMap((classA1)->{ return Optional.ofNullable(classA1.getClassB()); }); System.out.println(optional); }}

运行结果如下图所示。

11、orElse(T other),如果 Optional 的值存在则返回,否则返回 other,定义如下所示。

public T orElse(T other) { return value != null ? value : other;}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable(1); System.out.println(optional.orElse("value is null")); optional = Optional.ofNullable(null); System.out.println(optional.orElse("value is null")); }}

运行结果如下图所示。

12、orElseGet(Supplier extends T> supplier),功能与 orElse 类似,区别在于 orElse 可直接返回某个值,orElseGet 需要执行 supplier,并返回其结果,多了一个步骤,定义如下所示。

public T orElseGet(Supplier extends T> supplier) { return value != null ? value : supplier.get();}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable(1); System.out.println(optional.orElseGet(()->"value is null")); optional = Optional.ofNullable(null); System.out.println(optional.orElseGet(()->"value is null")); }}

运行结果如下图所示。

13、orElseThrow(),如果值存在则返回,否则抛出 NoSuchElementException,定义如下所示。

public T orElseThrow() { if (value == null) { throw new NoSuchElementException("No value present"); } return value;}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable(1); System.out.println(optional.orElseThrow()); optional = Optional.ofNullable(null); System.out.println(optional.orElseThrow()); }}

运行结果如下图所示。

14、orElseThrow(Supplier extends X> exceptionSupplier),功能与 orElseThrow 类似,如果值存在则返回,否则抛出 exceptionSupplier 返回的异常,定义如下所示。

public  T orElseThrow(Supplier extends X> exceptionSupplier) throws X { if (value != null) { return value; } else { throw exceptionSupplier.get(); }}

具体操作如下所示。

public class Test { public static void main(String[] args) { Optional optional = Optional.ofNullable(1); try { System.out.println(optional.orElseThrow(()->{throw new IllegalStateException();})); } catch (Throwable throwable) { throwable.printStackTrace(); } optional = Optional.ofNullable(null); try { System.out.println(optional.orElseThrow(()->{throw new IllegalStateException();})); } catch (Throwable throwable) { throwable.printStackTrace(); } }}

运行结果如下图所示。

上面详细介绍了 Optional 类的各种方法,接下来我们结合实际案例,来看看实际开发中使用 Optional 的优势。

实际案例

我们来设置一个客户订单查询场景。

1、定义 3 个类 Consumer、Order、Product,其中 Consumer 包含 Order,Order 包含 Product,具体代码如下所示。

public class Consumer { private Order order; public Order getOrder() { return order; } public void setOrder(Order order) { this.order = order; }}public class Order { private Product product; public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; }}public class Product { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }}

2、分别创建 Consumer、Order、Product 对象,并完成级联,然后定义返回 Consumer 中 ProductName 的方法,传统的开发方式需要对涉及到的对象都进行非空验证,如下所示。

public class Test { public static void main(String[] args) { Product product = new Product(); product.setName("电脑"); Order order = new Order(); order.setProduct(product); Consumer consumer = new Consumer(); consumer.setOrder(order); System.out.println(getProductName(consumer)); } public static String getProductName(Consumer consumer){ if(consumer != null){ Order order = consumer.getOrder(); if(order != null){ Product product = order.getProduct(); if(product != null){ return product.getName(); } } } return null; }}

3、使用 Optional 类对上述代码进行修改,可以将代码变得更加简洁、优雅,不需要一层一层的写非空判断,可直接完成链式调用,如下所示。

public static String getProductName(Consumer consumer){ return Optional.ofNullable(consumer) .map(consumer1 -> consumer1.getOrder()) .map(order -> order.getProduct()) .map(product -> product.getName()) .orElse(null);}

4、运行结果如下图所示。

关注微信公众号「Java大联盟」,关注即可获取海量学习干货,同时还有不定期送书,键盘,鼠标等粉丝福利。

赶快来关注一波,海量资源拿到手软。

optional 解决空指针_Java8新特性:Optional类的正确使用姿势相关推荐

  1. JDK8新特性-Optional类

    个人简介 作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门. 文章目录 个人简介 JDK8新特性-Option ...

  2. Java8新特性——Optional 类

    文章目录 前言 Optional 类 1.概述 2.API介绍 of ofNullable empty isPresent get ifPresent orElse orElseGet orElseT ...

  3. Java8新特性 Optional类

    作为开发人员每天与NullPointerException斗智斗勇.每接收到参数或调用方法获得值得判断一下是否为null.稍不留意,空指针异常就像幽灵一样出现了.这篇文章我们来学习Java8是如何通过 ...

  4. Java8新特性-Optional类

    概念:Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这 ...

  5. Java8新特性Optional类

    这里写自定义目录标题 Java8 Optional 类 前言 创建 Optional 实例 Optional API常用接口的用法 get()方法 isPresent()方法 isPresent()方 ...

  6. java 8 optional 类,Java8新特性-Optional类

    Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念.并且可以避免空指 ...

  7. Java JDK8新特性Optional类

    Optional类 1.该类java.util包下,是不能被继承的泛型类即:public final class Optional<T>. 2.该类有两个私有属性: T value和 静态 ...

  8. JDK1.8新特性 Optional判空详解,简化判空操作

    一.简介 从 Java 8 引入的一个很有趣的特性是 Optional 类.Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) -- 每个 Java ...

  9. optional转化为set_JDK8新特性--学习笔记(OptionalCollectors)

    Optional 为什么要用Optional为了避免空对象的出现,这是大家都知道的基础事实 Optional是函数交互的时候,不管是传参还是返回值,封装的Optional都能很好的规避null的情况. ...

最新文章

  1. 【java】兴唐第十七节课
  2. 次元网站女装穿起来,从A站到Z站,你知道哪个?谁才是你的最爱?
  3. SAP中的Currency Converting Factor
  4. 计算机基础ABCDEF,计算机应用基础-在线作业ABCDEF.docx
  5. antisamy java_antisamy的使用方法
  6. mssql与oracle不同点,MySql,Mssql,Oracle的优缺点和异同(欢迎补充) *
  7. g​e​t​A​t​t​r​i​b​u​t​e​和​g​e​t​P​a​r​a​m​e​t​e​r​区​别...
  8. 程序bug导致了天大的损失,要枪毙程序猿吗?
  9. 6 万出头的北京房价,程序员如何靠自己安家?
  10. 进军企业服务器 Ubuntu准备好了吗?
  11. node -v 突然显示 killed 9 处理历程
  12. 没了珊瑚虫你用谁?八大QQ主流修改版大比拼
  13. 【已解决】ws2_32.dll丢失怎么办?ws2_32.dll调用失败如何修复
  14. windows下载安装adb(极其简单)
  15. Linux虚拟机远程连接工具
  16. Vue实现百度离线地图(v2.0)
  17. 易优EyouCMS全套插件使用说明
  18. 康托尔连续统假设正确吗?
  19. LAMMPS案例分析——水滴的蒸发
  20. cad字体安装_如何安装CAD字体库,让打开图纸时显示quot;?quot;的现象都消失?【AutoCAD教程】...

热门文章

  1. php 8.0 jit,PHP 8.0 正式版发布,性能提升 10%
  2. Python:IPython性能度量
  3. QT禁用“最大化按钮“和“禁止调节窗口大小“
  4. 针织布横条疵点解决方案
  5. git理解HEAD,master
  6. mysql查询,left join(求并集),where(求交集)
  7. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合...
  8. c++全局变量的声明和使用
  9. 创建Windows Mobile上兼容性好的UI 程序
  10. AjaxAtlas技术团队[公告]:请大家清理自己发布在团队页面上的post!