个人简介

作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门。

文章目录

  • 个人简介
  • JDK8新特性-Optional类
    • 教程概述
    • Optional的简单介绍
    • 简单对比两种防止空指针方式
      • 准备环境
      • JDK1.8之前的普通方式
      • JDK1.8之后使用Optional方式
    • 创建Optional实例的三种方式
      • of方法
        • of方法创建Optional实例
        • 为什么of方法的值不能为null,否则就会报错?源码分析
      • ofNullable方法
        • ofNullable方法创建Optional实例
        • 为什么ofNullable方法的值可以为null?源码分析
      • empty方法
        • empty方法源码分析
    • isPresent方法
      • isPresent方法的使用
      • isPresent源码分析
    • ifPresent方法
      • ifPresent方法使用
      • ifPresent源码分析与isPresent区别
    • orElse方法
      • orElse方法源码解析
    • orElseGet方法
      • orElseGet方法使用
      • orElseGet源码解析
    • orElse和orElseGet区别
    • orElseThrow方法
    • filter方法
    • map方法
      • 案例:传入User对象,返回UserDetail对象

JDK8新特性-Optional类

教程概述

  • 本教程附有非常多的例子,看完肯定能懂Optional类!
  • 看完本教程,对于Optional类的api基本的使用完全没有问题!
  • 本教程借鉴过很多其他大佬的教程,并进行总结创新,难免会有相同之处。
  • 本教程会涉及一些源码。

Optional的简单介绍

  • 每个程序员都会遇到的Exception其中最常见的莫过于NullPointerException异常,为了避免这个异常的发生我们常用if去判断对象是否为null再进行使用,这样就显得很乏味,于是Optional出现了。
  • Optional的好处是:使用链式编程的方式更优雅的解决NullPointerException问题

简单对比两种防止空指针方式

准备环境

   //准备环境User user = new User();user.setUsername("aaa");UserDetail userDetail = new UserDetail();userDetail.setIcon("icon");userDetail.setSignature("ccccd");user.setUserdetail(userDetail);UserAuthority userAuthority = new UserAuthority();userAuthority.setAuthority(2);userDetail.setUserAuthority(userAuthority);
class User{private String username; //用户名private UserDetail userdetail; //用户细节//省略getter/setter/tostring
}
class UserDetail{private String icon;//头像private String signature;//个性前面private UserAuthority userAuthority; //用户权限//省略getter/setter/tostring
}
class UserAuthority{private int authority; //权限//省略getter/setter/tostring
}

JDK1.8之前的普通方式

      //JDK1.8之前,如果我们要查询用户权限。要这样子if(user!=null){if(user.getUserdetail()!=null){if(user.getUserdetail().getUserAuthority()!=null){System.out.println("JDK1.8之前查权限:"+user.getUserdetail().getUserAuthority().getAuthority());}else {System.out.println(333);}}}

JDK1.8之后使用Optional方式

   //JDK1.8之后,如果我们要查询用户权限。可以使用Optional类Integer integer = Optional.ofNullable(user)//还没有经过map,当前stream是:user对象//经过了第一次map变成userdetail对象.map(u -> u.getUserdetail())//经过了第二次userauthority.map(ud -> ud.getUserAuthority())//authority.map(a -> a.getAuthority())//如果哪一层map出现null了,则会直接跳到下面这个orElse去执行。.orElse(333);System.out.println(integer);

创建Optional实例的三种方式

  • 由于Optional类的构造方法全部都被private修饰,所以不能通过new关键字去创建,必须要通过以下三种方法进行创建。
 private Optional() {this.value = null;}private Optional(T value) {this.value = Objects.requireNonNull(value);}
  • Optional类被final进行修饰,故无法对它进行继承。
public final class Optional<T> {Optional类核心代码
}

of方法

of方法的特点:

  • 不允许Optional的value为null否则会立刻报错NullPointerException异常
of方法创建Optional实例
Optional<String> stringOptional = Optional.of("hello");
为什么of方法的值不能为null,否则就会报错?源码分析
    public static <T> Optional<T> of(T value) {return new Optional(value);}private Optional(T value) {this.value = Objects.requireNonNull(value);}

Objects.requireNonNull源码

 public static <T> T requireNonNull(T obj) {if (obj == null) {throw new NullPointerException();} else {return obj;}}

ofNullable方法

  • ofNullable的value可以为null,并且不会报错
ofNullable方法创建Optional实例
Optional<Object> optional = Optional.ofNullable("hello");
为什么ofNullable方法的值可以为null?源码分析
 public static <T> Optional<T> ofNullable(T value) {return value == null ? empty() : of(value);}
  • 可以看出当value==null时,此时Optional的对象由empty方法创建,而empty方法的返回的Optional对象是由Optional类内部实例化的一个Optional实例,名字为EMPTY,并且是被private static final修饰。
 private static final Optional<?> EMPTY = new Optional(); public static <T> Optional<T> empty() {Optional<T> t = EMPTY;return t;}
  • 当value!=null时,则调用of方法进行创建,虽然of方法不能为null否则会报错,但是此时的value一定不为空,所以of方法一定不会报错。故这个ofNullable方法一定不会报错。

empty方法

  • empty方法的返回的Optional对象是由Optional类内部实例化的一个Optional实例,名字为EMPTY,并且是被private static final修饰
empty方法源码分析
 private static final Optional<?> EMPTY = new Optional(); public static <T> Optional<T> empty() {Optional<T> t = EMPTY;return t;}

isPresent方法

  • 判断Optional的value是否存在,也就是是否不为null

isPresent方法的使用

 //准备环境User user = new User();user.setUsername("aaa");UserDetail userDetail = new UserDetail();userDetail.setIcon("icon");userDetail.setSignature("ccccd");user.setUserdetail(userDetail);UserAuthority userAuthority = new UserAuthority();userAuthority.setAuthority(2);userDetail.setUserAuthority(userAuthority);Optional<User> optionalUser = Optional.ofNullable(user);boolean present = optionalUser.isPresent();System.out.println("Optional的value是否存在?"+present);if(present){System.out.println(optionalUser.get()); //此时一定不为null,present为true代表存在}

isPresent源码分析

 private final T value;  public boolean isPresent() {return this.value != null;}
  • Optional一旦创建,就会往value放值,isPresent方法的作用就是判断value是否不为空,也就是是否存在

  • 还有就是String s="",也代表存在,而String s=null,则是不存在。

ifPresent方法

  • 一定要区别于isPresent和ifPresent方法。

ifPresent方法使用

 Optional<String> optionalS = Optional.ofNullable(null);//如果Optional的value存在则会执行System.out.println("ifpresent="+s)这段代码,反之则不会执行。optionalS.ifPresent(s->System.out.println("ifpresent="+s));

ifPresent源码分析与isPresent区别

 public void ifPresent(Consumer<? super T> action) {if (this.value != null) {action.accept(this.value);}}
  • ifPresent没有返回值,接收参数是lambda表达式,如果this.value不会空才会执行这个lambda表达式。
 public boolean isPresent() {return this.value != null;}
  • 而isPresent方法是不用参数的,并且返回boolean值,也是判断this.value是否存在。本质上都差不多

orElse方法

  • 当optional的value为null,或者经过map映射的optional的value为null,则会执行orElse方法
  • 本质上orElse方法就是当optional的value为null时的兜底方法。
   Optional<String> optional1 = Optional.ofNullable("hello");String s1 = optional1.orElse("orElse111---");System.out.println(s1); //helloOptional<String> optional2 = Optional.ofNullable(null);String s2 = optional2.orElse("orElse222---");System.out.println(s2); // orElse222---

orElse方法源码解析

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

意思是如果this.value如果存在,返回结果就是这个value,如果value不存在,则会返回other,other就是我们的兜底方案。

orElseGet方法

  • orElse和orElseGet差不多,只是形参不同,orElseGet需要传入lambda的Supplier 表达式,格式为:()->xxx

orElseGet方法使用

  Object o = Optional.ofNullable(null).orElseGet(() -> "orElseGet");System.out.println(o);

orElseGet源码解析

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

如果this.value存在,则返回this.value,反之则使用传过来的supplier的值

orElse和orElseGet区别

  • 如果optional的value!=null,orElse方法也要执行。即使value不为null,也要执行。
  • 而orElseGet方法只有value==null才会执行
  • 对于orElse方法这种特性是极其浪费性能的。
  private static String getName() {System.out.println("getname");return "张三";}     String s1 = Optional.ofNullable("666").orElse(getName());System.out.println(s1);

输出

getname
666
  private static String getName() {System.out.println("getname");return "张三";}     String s2 = Optional.ofNullable("777").orElseGet(() -> getName());System.out.println(s2);

输出

777

orElseThrow方法

  • 其实就是当value为null时,兜底方法就是抛自定义异常。
   String n=null;String s = Optional.ofNullable(n).orElseThrow(() -> new RuntimeException("excp"));System.out.println(s);

输出

Exception in thread "main" java.lang.RuntimeException: excpat com.jdk8.optional.Optional06.lambda$main$0(Optional06.java:11)at java.base/java.util.Optional.orElseThrow(Optional.java:408)at com.jdk8.optional.Optional06.main(Optional06.java:11)

filter方法

filter方法的使用请参照我的一篇Stream流的教程。。。

  • 其实filter过滤就像是if语句,只把符合条件的筛选出来。

使用

   //准备环境User user1 = new User();user1.setUsername("aaa");User user2 = new User();user2.setUsername("bbb");User user3 = new User();user3.setUsername("ccc");Optional<User> optionalUser1 = Optional.ofNullable(user1).filter(x -> x.getUsername().equals("bbb"));System.out.println(optionalUser1);//Optional.emptyOptional<User> optionalUser2 = Optional.ofNullable(user2).filter(x -> x.getUsername().equals("bbb"));//Optional[User{username='bbb', userdetail=null}]System.out.println(optionalUser2);

输出

Optional.empty
Optional[User{username='bbb', userdetail=null}]

map方法

map方法的使用请参照我的一篇Stream流的教程。。。

  • map的作用就是把一个对象进行转换,比如下面的,map的作用就是把User对象转换成UserDetail对象。

案例:传入User对象,返回UserDetail对象

   //准备环境User user = new User();user.setUsername("aaa");UserDetail userDetail = new UserDetail();userDetail.setIcon("icon");userDetail.setSignature("ccccd");user.setUserdetail(userDetail);UserAuthority userAuthority = new UserAuthority();userAuthority.setAuthority(2);userDetail.setUserAuthority(userAuthority);//传入User对象,返回UserDetail对象Optional<UserDetail> optionalUserDetail =Optional.of(user).map(User::getUserdetail);System.out.println(optionalUserDetail.get());

输出

UserDetail{icon='icon', signature='ccccd', userAuthority=UserAuthority{authority=2}}

JDK8新特性-Optional类相关推荐

  1. JDK8新特性 - Optional类

    引言 Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException).本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空 ...

  2. Java JDK8新特性Optional类

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

  3. Java8新特性——Optional 类

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

  4. Java8新特性 Optional类

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

  5. Java8新特性Optional类

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

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

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

  7. Java8新特性-Optional类

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

  8. Java 8 新特性 Optional 类学习,理解并应用。NullPointerException空值检测

  9. JDK8 新特性流式数据处理

    在学习JDK8新特性Optional类的时候,提到对于Optional的两个操作映射和过滤设计到JDK提供的流式出来.这篇文章便详细的介绍流式处理: 一. 流式处理简介 流式处理给开发者的第一感觉就是 ...

最新文章

  1. mooc python_MOOC python笔记(一):python语言概述
  2. 图解在emu8086中学习汇编语言数字比较程序
  3. SpringBoot 上传文件(单个、多个文件)
  4. Jenkins+GitLab+Docker+SpringCloud+Kubernetes实现可持续自动化微服务
  5. 物联网技术周报第 109 期: 从设计理念解读实时操作系统 RT-Thread
  6. Nginx从入门到掌握【(第3节(共3节)】
  7. LeetCode 513. 找树左下角的值(递归)
  8. Oracle安装基本步骤
  9. 楼房噪音模拟测试软件,房子不隔音?4种方法让你进入“静音”模式!
  10. CC2530单片机P1寄存器说明
  11. js笔记,自封装篇(二)之对象克隆
  12. python打印日历_用Python打印某年日历
  13. echarts图表和map地图
  14. 洛谷 P4238 【模板】多项式求逆 ntt
  15. Graphpad,经典绘图工具初学初探
  16. 如何快速生成gif动图表情包?教你制作gif表情包图片
  17. American Crew(R) ACUMEN™闪亮登场
  18. 不知道如何提高视觉语言大模型?浙大与联汇研究院提出新型多维度评测框架...
  19. Linq之GroupBy用法
  20. FDC2214-纸张计数显示装置

热门文章

  1. 查看linux系统重启时间历史记录
  2. SSM三大框架的运行流程、原理、核心技术详解!
  3. 最小二乘法的一阶、二阶辨识系统
  4. 【电商数仓】数仓搭建之DIM维度层(商品、优惠券、活动、地区、时间维度表)
  5. 写一个函数,输入一个4位数字,要求输出这4个数字字符,但每两个数字间空一格空格。如输入1990,应输出”1 9 9 0“
  6. MyBatis--事务
  7. 机器学习的算法有啥都不知道?8 个真实项目带你入门
  8. 网赚自媒体圈钱攻略 年入百万不在话下
  9. sqlserver删除表字段报错解决方案
  10. junit mock服务器文件,mock数据的几种姿势