文章目录

  • API介绍
    • 第一组
      • Optional(T value)
      • empty()
      • of(T value)
      • ofNullable(T value)
    • 第二组
      • orElse(T other),orElseGet(Supplier other)
      • orElseThrow(Supplier exceptionSupplier)
    • map(Function mapper)和flatMap(Function> mapper)
    • isPresent()和ifPresent(Consumer consumer)
    • filter(Predicate predicate)
  • 案例
    • 例子1
    • 例子2
    • 例子3

Java8 提供了Optional类来优化判空写法。
Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。

API介绍

第一组

这四个函数之间具有相关性,因此放在一起;

Optional(T value)

Optional(T value),即构造函数,它是private权限的,不能由外部调用的。

 /*** Constructs an instance with the described value.** @param value the non-{@code null} value to describe* @throws NullPointerException if value is {@code null}*/private Optional(T value) {this.value = Objects.requireNonNull(value);}

其余三个函数是public权限,供我们所调用。

empty()

Optional类内部还维护一个value为null的对象,大概就是长下面这样的:

public final class Optional<T> {//省略....private static final Optional<?> EMPTY = new Optional<>();private Optional() {this.value = null;}//省略...public static<T> Optional<T> empty() {@SuppressWarnings("unchecked")Optional<T> t = (Optional<T>) EMPTY;return t;}
}

empty() 的作用就是返回EMPTY对象。

of(T value)

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

of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:

  • 通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。
  • 通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。

使用场景:
当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。

ofNullable(T value)

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

相比较of(T value)的区别就是:
当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。

第二组

这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。

orElse(T other),orElseGet(Supplier other)

详细API源码如下:

/*** Return the value if present, otherwise return {@code other}.** @param other the value to be returned if there is no value present, may* be null* @return the value, if present, otherwise {@code other}*/
public T orElse(T other) {return value != null ? value : other;
}/*** Return the value if present, otherwise invoke {@code other} and return* the result of that invocation.** @param other a {@code Supplier} whose result is returned if no value* is present* @return the value if present otherwise the result of {@code other.get()}* @throws NullPointerException if value is not present and {@code other} is* null*/
public T orElseGet(Supplier<? extends T> other) {return value != null ? value : other.get();
}

orElse和orElseGet的用法如下所示,相当于value值为null时,给予一个默认值:

public class OptionalTest {public static void main(String[] args) throws Exception {// Person person = null;Person person = new Person();Person person1 = Optional.ofNullable(person).orElse(creatPerson());System.out.println(person1);Person person2 = Optional.ofNullable(person).orElseGet(() -> creatPerson());System.out.println(person2);Optional.ofNullable(person).orElseThrow(() -> new Exception("没有此人"));}public static Person creatPerson() {Person person = new Person();person.setName("Tom");person.setAge(18);person.setNickName("cat");System.out.println("create person");return person;}
}

这两个函数的区别:

上面的测试可以发现。
当person值不为null时,orElse函数依然会执行creatPerson()方法,
而orElseGet函数并不会执行creatPerson()方法;

orElseThrow(Supplier exceptionSupplier)

orElseThrow,就是value值为null时,直接抛一个异常出去:

/*** Return the contained value, if present, otherwise throw an exception* to be created by the provided supplier.** @apiNote A method reference to the exception constructor with an empty* argument list can be used as the supplier. For example,* {@code IllegalStateException::new}** @param <X> Type of the exception to be thrown* @param exceptionSupplier The supplier which will return the exception to* be thrown* @return the present value* @throws X if there is no value present* @throws NullPointerException if no value is present and* {@code exceptionSupplier} is null*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {if (value != null) {return value;} else {throw exceptionSupplier.get();}
}

map(Function mapper)和flatMap(Function> mapper)

两个函数做的是转换值的操作:

public final class Optional<T> {//省略....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));}}//省略...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));}}
}

这两个函数,在函数体上没什么区别。唯一区别的就是入参。
map函数所接受的入参类型为Function<? super T, ? extends U>,
而flapMap的入参类型为Function<? super T, Optional<U>>。

示例1:

public class OptionalMapFilterDemo {public static void main(String[] args) {String password = "password";Optional<String>  opt = Optional.ofNullable(password);Predicate<String> len6 = pwd -> pwd.length() > 6;Predicate<String> len10 = pwd -> pwd.length() < 10;Predicate<String> eq = pwd -> pwd.equals("password");boolean result = opt.map(String::toLowerCase).filter(len6.and(len10 ).and(eq)).isPresent();System.out.println(result);}
}

示例2:

public class Person {private String name;private int age;private String nickName;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Optional<String> getNickName() {return Optional.ofNullable(nickName);}public void setNickName(String nickName) {this.nickName = nickName;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", nickName='" + nickName + '\'' +'}';}
}
public static void testMap() {Person newPerson = creatPerson();Integer age = Optional.ofNullable(newPerson).map(e -> e.getAge()).get();System.out.println("newPerson age = " + age);String nickName = Optional.ofNullable(newPerson).flatMap(e -> e.getNickName()).get();System.out.println("newPerson nickName = " + nickName);
}

isPresent()和ifPresent(Consumer consumer)

这两个函数放在一起记忆,isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。

filter(Predicate predicate)

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。

案例

例子1

比如,在主程序中

以前写法

if(user!=null){dosomething(user);
}

java8写法

 Optional.ofNullable(user).ifPresent(u->{dosomething(u);
});

例子2

在函数方法中

以前写法

public String getCity(User user)  throws Exception{if(user!=null){if(user.getAddress()!=null){Address address = user.getAddress();if(address.getCity()!=null){return address.getCity();}}}throw new Excpetion("取值错误");}

java8写法

public String getCity(User user) throws Exception{return Optional.ofNullable(user).map(u-> u.getAddress()).map(a->a.getCity()).orElseThrow(()->new Exception("取指错误"));
}

例子3

以前写法

public User getUser(User user) throws Exception{if(user!=null){String name = user.getName();if("zhangsan".equals(name)){return user;}}else{user = new User();user.setName("zhangsan");return user;}
}

java8写法

public User getUser(User user) {return Optional.ofNullable(user).filter(u->"zhangsan".equals(u.getName())).orElseGet(()-> {User user1 = new User();user1.setName("zhangsan");return user1;});
}

采用这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。

Java8 Optional类用法相关推荐

  1. 新容器!不再担心空指针, Java8 Optional类

    Optional<T>类(java.util.Optional)是一个容器类,它可以保存类型T的值,代表这个值存在.或者仅仅保存null,表示这个值不存在.原来用 null 表示一个值不存 ...

  2. Java8 Optional类

    概述 到目前为止,著名的NullPointerException是导致Java应用程序失败的最常见原因.过去,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guav ...

  3. Java8新特性Optional类

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

  4. Java8新特性 Optional类

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

  5. Java8新特性学习_001_(Lambda表达式,函数式接口,方法引用,Stream类,Optional类)

    目录 ■代码 ■代码运行结果 ■代码说明 ・44行:Stream的.foreach方法ー参数类型:函数式接口 ・82行:Interface中,default方法 ・92行   Stream的.max方 ...

  6. Java8新特性之空指针异常的克星Optional类

    Java8新特性系列我们已经介绍了Stream.Lambda表达式.DateTime日期时间处理,最后以"NullPointerException" 的克星Optional类的讲解 ...

  7. 如何正确的使用Java8中的Optional类来消除代码中的null检查

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:一书生VOID lw900925.github.io/jav ...

  8. 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类

    1.Lambda表达式 用匿名内部类的方法去创建多线程1.new Thread2.参数传递new Runnable3.重写run方法4.在run方法中去设置线程任务5.调用start问题:我们最终目标 ...

  9. java8新特性(5)— Optional 类

    java8新特性(5)- Optional 类 空指针解决方案 package com.common.jdk8;import java.util.Optional;//Optional 类是一个可以为 ...

最新文章

  1. Set 、HashSet、TreeSet、LinkedHashSet、EnumSet
  2. bert简介_关于BERT:你不知道的事
  3. matlab parfor不能用,matlab中parfor函数
  4. mysql遇到时区问题的坑(Java解决方案)
  5. 实现IButtonControl接口时, PerformClick()方法的代码怎么写,请高手指导!
  6. android开发ui插件下载,TKUISDK-ANDROID
  7. 百度编辑器回显js报错Uncaught SyntaxError: Invalid or unexpected token
  8. SpringCloud学习笔记028---在SpringBoot中整合多数据源_实战项目
  9. c语言父 app,90后父母最爱的10款实用APP,中老年人必备!
  10. 用Visio画UML顺序图
  11. 141个关于人工智能的统计数据
  12. 【LaTex】6.4 listings高亮设置
  13. 视频号直播间微信小程序开发制作介绍
  14. 华为的服务器虚拟化软件,服务器虚拟化软件
  15. 艾默生质量流量计调试
  16. CentOS7安装onlyoffice实现word的在线预览和编辑
  17. 什么是集合,集合和数组的区别是什么
  18. MBR与GPT分区的区别及使用注意事项(转载)
  19. Hive性能优化(全面)解决数据倾斜等问题
  20. 碎影录·Freshman In SDU by郝宗铎

热门文章

  1. go中的G.M.P以及Goroutine、Scheduler
  2. Samba无法连接问题解决方法
  3. MongoDB 慢查询优化
  4. 超快速实现 svg 转 png,jpg等格式
  5. gparted使用 ubuntu_如何使用GParted扩展Ubuntu14.04根目录
  6. [C#小技巧]如何捕捉上升沿和下降沿
  7. java黄油刀_github 黄油刀(注解) butterknife
  8. 读博、求知与人生规划
  9. 池建强:如何学习一门编程语言
  10. 第三方服务接口调用方式记录