Java8新特性——Optional类的使用(有效的避免空指针异常)
OPtional类的使用
概述
到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。
Optional类的常用方法:
Optional.empty() : 创建一个空的 Optional 实例
Optional.of(T t) : 创建一个 Optional 实例
Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
isPresent() : 判断是否包含值
T get(): 如果调用对象包含值,返回该值,否则抛异常
orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
代码演示
/**
*
*/
package com.xnn.Optional;
import java.util.Optional;
import org.junit.Test;
import com.xnn.lambda.Person;
/**
* 类(接口)描述: Optional.of(T t) : 创建一个 Optional 实例 Optional.empty()
* :创建一个空的Optional实例 Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
* isPresent() : 判断是否包含值 T get(): 如果调用对象包含值,返回该值,否则抛异常 orElse(T t) :
* 如果调用对象包含值,返回该值,否则返回t orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
* map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
* flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
*
* @author xnn 2018年10月25日下午2:12:54
*/
public class TestOptional {
@Test
public void test() {
// Optional.of(T t) : 创建一个 Optional 实例,参数也可为null 表示把null封装进了OPtional容器
Optional<Person> optional = Optional.of(new Person("李四", 59, 6666.66));
// T get(): 如果调用对象包含值,返回该值,否则抛异常
Person person = optional.get();
System.out.println("person" + person);
System.out.println("===========");
// 参数设为null的情况 会报空指针异常
Optional<Person> optiona2 = Optional.of(null);
System.out.println(optiona2.get());
}
@Test
public void test1() {
// Optional.empty() :创建一个空的Optional实例
Optional<Person> empty = Optional.empty();
// 因为Optional容器里面是空的 所以报了个NoSuchElementException,这样容易定位空指针
// 和Optional.of(null)还不太一样。Optional.of(null).get()就报了个空指针
System.out.println("empty.get():" + empty.get());
}
@Test
public void test2() {
// Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
Optional<Object> nullable = Optional.ofNullable(null);
// T为null创建空实例,融合了of()方法的缺陷
System.out.println("nullable:" + nullable);
}
@Test
public void test3() {
Optional<Object> nullable = Optional.ofNullable(null);
// isPresent() : 判断是否包含值 nullable为空 所以返回false
boolean present = nullable.isPresent();
System.out.println("present:" + present);
}
@Test
public void test4() {
Optional<Person> optional = Optional.of(new Person("李四", 59, 6666.66));
// orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
// 就是先看optional这个容器里面有值与否 若有,则直接返回 若没有 返回T
Object orElse = optional.orElse(new Person());
System.out.println(orElse);
}
@Test
public void test5() {
// orElseGet(Supplier s) :如果调用对象(调用者是Optional类)包含值,返回该值,否则返回 s 获取的值
// 和上面不同的是这里的参数需要我们提供一个Supplier类型的函数式接口
// ,这样我们就可以在Lambda表达式体中写自己的逻辑没最后返回个T
Optional<Person> optional = Optional.of(new Person("李四", 59, 6666.66));
Person orElseGet = optional.orElseGet(() -> new Person());
// 因为optional包含的对象是有值的。所以返回new Person("李四", 59, 6666.66)
System.out.println("orElseGet:" + orElseGet);
Optional<Object> nullable = Optional.ofNullable(null);
// 这个nulllable时空的
Object elseGet = nullable.orElseGet(() -> new Person());
// 所以返回参数(函数式接口与返回的值,即无参构造器返回的是默认值)
System.out.println("elseGet:" + elseGet);
}
@Test
public void test6() {
// map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
Optional<Person> optional = Optional.of(new Person("李四", 59, 6666.66));
Optional<String> map = optional.map(Person::getName);
System.out.println("map:"+map);
}
@Test
public void test7() {
// flatMap(Function mapper):与 map 类似,
Optional<Person> optional = Optional.of(new Person("李四", 59, 6666.66));
//要求返回值必须是Optional 所以在参数那里 Lambda表达式的返回值用Optional包装了一层
Optional<String> flatMap = optional.flatMap((e) -> Optional.of(e.getName()));
System.out.println("flatMap"+flatMap);
}
}
运行结果

nullable:Optional.empty
present:false
Person [name=李四, age=59, salary=6666.66, status=null]
orElseGet:Person [name=李四, age=59, salary=6666.66, status=null]
elseGet:Person [name=null, age=0, salary=0.0, status=null]
map:Optional[李四]
flatMapOptional[李四]
一个小应用场景
父亲类:
package com.xnn.Optional;
/**
* 类(接口)描述:
* @author xnn
* 2018年10月25日下午3:21:31
*/
public class Father {
private Son son;
public Father() {
super();
}
public Father(Son son) {
super();
this.son = son;
}
public Son getSon() {
return son;
}
public void setSon(Son son) {
this.son = son;
}
@Override
public String toString() {
return "Father [son=" + son + "]";
}
}
son 类
package com.xnn.Optional;
/**
* 类(接口)描述:
* @author xnn
* 2018年10月25日下午3:21:51
*/
public class Son {
private String name;
public Son() {
super();
}
public Son(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Son [name=" + name + "]";
}
}
现做一个小功能 传进来一个Father对象 返回他的儿子的名字 为了确保不出现空指针异常,我们通常的做法是
1、判断传进来的Father是否为空,若为空 什么也不做 若不为空 获取其son属性
2、判断son是否为空 若为空 返回null 若不为空 调用son的getName()方法进行返回
若属性太多,或者是包装的层数过多,则会导致很深的if嵌套 造成代码可读性变差
因此 我们改变Father类 把son属性用Optional类包装
/**
*
*/
package com.xnn.Optional;
import java.util.Optional;
/**
* 类(接口)描述:
* @author xnn
* 2018年10月25日下午3:30:00
*/
public class Father2 {
private Optional<Son> son =
//保证OPtional类不为空
Optional.empty();
public Father2() {
super();
}
public Father2(Optional<Son> son) {
super();
this.son = son;
}
public Optional<Son> getSon() {
return son;
}
public void setSon(Optional<Son> son) {
this.son = son;
}
@Override
public String toString() {
return "Father2 [son=" + son + "]";
}
}
测试类
@Test
public void test8() {
Father father =new Father();
//报了个空指针
//getSonName(father);
//可以用if判断语句嵌套判断 避免空指针 但若嵌套太深 代码可读性也会变差
Optional<Father2> optional = Optional.ofNullable(new Father2(Optional.ofNullable(new Son("小明"))));
System.out.println(getSonName1(optional));;
}
//需求:获取父亲的儿子的名字
public String getSonName(Father father) {
return father.getSon().getName();
}
//传进来的father也有可能为空 所以用Optional包装
public String getSonName1(Optional<Father2> optional) {
//若传进来的对象为空没给一个默认值,保证了传进来的对象不会为空
return optional.orElse(new Father2())
.getSon()
//这个人可能还没有儿子,若没有 默认为孙悟空 避免了getName()方法的空指针
.orElse(new Son("孙悟空"))
.getName();
}
结果
小明
Java8新特性——Optional类的使用(有效的避免空指针异常)的更多相关文章
- Java8 新特性 Optional 类
Optional 类的简介 Optional类的是来自谷歌Guava的启发,然后就加入到Java8新特性中去了.Optional类主要就是为子决解价值亿万的错误,空指针异常. Optional ...
- JDK1.8新特性——Optional类
JDK1.8新特性——Optional类 摘要:本文主要学习了JDK1.8新增加的Optional类. 部分内容来自以下博客: https://www.cnblogs.com/1ning/p/9140 ...
- Java8新特性——Optional
前言 在开发中,我们常常需要对一个引用进行判空以防止空指针异常的出现.Java8引入了Optional类,为的就是优雅地处理判空等问题.现在也有很多类库在使用Optional封装返回值,比如Sprin ...
- JAVA8新特性Optional,非空判断
Optional java 的 NPE(Null Pointer Exception)所谓的空指针异常搞的头昏脑涨, 有大佬说过 "防止 NPE,是程序员的基本修养." 但是修养归 ...
- Java8新特性--Optional
Java 8引入了一个新的Optional类.Optional类的Javadoc描述如下: 这是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会 ...
- java8 新特性 -Optional的常见用法
1. Optional 一. 简介 Opitonal是java8引入的一个新类,目的是为了解决空指针异常问题.本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为 ...
- Java8新特性Optional、接口中的默认方法与静态方法
Optional Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念 ...
- Java8新特性 - Optional容器类
Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念.并且可以避免空指针异 ...
- java8 新特性 Optional容器类
public class Godness { private String name; public Godness() { } public Godness(String name) { this. ...
随机推荐
- 天天向上的力量python(举一反三)
天天向上的力量python实例(举一反三) 实例1: 一年365天,以第1天的能力值为基数,记为1.0,当好好学习时能力值相比前一天提高0.1%,没有学习实能力值相比前一天下降0.1%. 问:每天努力 ...
- CAD绘图大师都在用的46组快捷键,高效绘图必备
学习CAD 是一个需要慢慢积累的过程,千万不要遇到一点小困难就退缩,有困难我们就一起克服它!今天小编也是来帮助大家克服困难的!很多小伙伴学习CAD已经有一段时间了,但是发现自己的绘图效率还是不高,没关 ...
- 基于vue+uniapp直播项目|uni-app仿抖音/陌陌直播室
一.项目简介 uni-liveShow是一个基于vue+uni-app技术开发的集小视频/IM聊天/直播等功能于一体的微直播项目.界面仿制抖音|火山小视频/陌陌直播,支持编译到多端(H5.小程序.Ap ...
- JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼?
<JavaScript 深入浅出>系列: JavaScript 深入浅出第 1 课:箭头函数中的 this 究竟是什么鬼? JavaScript 深入浅出第 2 课:函数是一等公民是什么意 ...
- Xcode 7.3 解决自定义类无法自动联想
正在苦拼的码友们,最近是不是觉得在写代码的时候很是头疼,甚至连个最基本的系统自带的语法啊.单词啊等等都不能联想了,之前习惯了的码友们,这个时候肯定会觉得是不是自己写错了,然后也往下翻了一大篇,还是找不 ...
- Gradle使用的简单了解
Gradle 认识 参考博客:http://www.enjoytoday.cn/categorys/Gradle gradle是一个用于构建工程的工程配置脚本,它可以很便捷的帮助我们构建管理工程结构, ...
- 论文学习-混沌系统以及机器学习模型-11-29-wlg
混沌系统以及机器学习模型 概述: 必要条件下: negative values of the sub-Lyapunov exponents. 通过rc方法, 可以在参数不匹配的情况下,实现输入信号,混 ...
- 删除带外键的表【foreign key constraint fails】报错
title: 删除带外键的表[foreign key constraint fails]报错 date: 2018-08-02 21:59:06 tags: 数据库 --- 遥想当时正在学hibern ...
- 记录一下自己在MVC项目中如何防CSRF攻击,直接上代码
1.前端的处理: 2.后台 1.)添加过滤器,哪里用放哪里 2.)需要验证的方法上直接添加过滤器即可 大功告成 以下为过滤器代码块 /// <summary>/// ajax中加上Anti ...
- Centos7安装vsftp服务
我们需要向centos操作系统的服务器上上传文件或者下载文件,这时候,ftp有必要安装下, 我们选择主流的vsftp: 第一步:安装vsftp yum install -y vsftpd 第二步:设置 ...