Optional源码级详解

认识Optional

Opitonal类就是Java提供的为了解决大家平时判断对象是否为空用,通常会用 null!=obj 这样的方式存在的判断,从而令人头疼导致空指针异常,同Optional的存在可以让代码更加简单,可读性跟高,代码写起来更高效

Student student = new Student();
if (null == student){return "student为null";
}
return student;//----------------------------//
Student student = new Student();
return Optional.ofNullable(student).orElse("student为null");

测试展示类Student 代码(如果有朋友不明白可以看一下这个):

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private Integer age;
}

Optional对象创建

首先我们先打开Optional的内部,去一探究竟 先把几个创建Optional对象的方法提取出来

public final class Optional<T> {private static final Optional<?> EMPTY = new Optional<>();private final T value;// 我们可以看到两个构造方格都是private 私有的// 说明 我们没办法在外面去new出来Optional对象private Optional() {this.value = null;}private Optional(T value) {this.value = Objects.requireNonNull(value);}// 这个静态方法大致 是创建出一个包装值为空的一个对象因为没有任何参数赋值public static<T> Optional<T> empty() {@SuppressWarnings("unchecked")Optional<T> t = (Optional<T>) EMPTY;return t;}// 这个静态方法大致 是创建出一个包装值非空的一个对象 因为做了赋值public static <T> Optional<T> of(T value) {return new Optional<>(value);}// 这个静态方法大致是 如果参数value为空,则创建空对象,如果不为空,则创建有参对象public static <T> Optional<T> ofNullable(T value) {return value == null ? empty() : of(value);}}

再做一个简单的实例展示 与上面对应

// 1、创建一个包装对象值为空的Optional对象
Optional<String> optEmpty = Optional.empty();
// 2、创建包装对象值非空的Optional对象
Optional<String> optOf = Optional.of("optional");
// 3、创建包装对象值允许为空也可以不为空的Optional对象
Optional<String> optOfNullable1 = Optional.ofNullable(null);
Optional<String> optOfNullable2 = Optional.ofNullable("optional");

Optional.get()方法(返回对象的值)

get()方法是返回一个option的实例值

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

也就是如果value不为空则做返回,如果为空则抛出异常 “No value present” 简单实例展示

Student student = new Student();
student.setAge(18);
System.out.println(Optional.ofNullable(student).get());

Optional.isPresent()方法(判读是否为空)

isPresent()方法就是会返回一个boolean类型值,如果对象不为空则为真,如果为空则false

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

简单的实例展示:

Student student = new Student();
student.setAge(18);
if (Optional.ofNullable(student).isPresent()){System.out.println("不为空");
}else {System.out.println("为空");
}

Optional.ifPresent()方法(判读是否为空并返回函数)

这个意思是如果对象非空,则运行函数体

public void ifPresent(Consumer<? super T> consumer) {//如果value不为空,则运行accept方法体if (value != null)consumer.accept(value);
}

看实例:

Student student = new Student();
student.setAge(18);
Optional.ofNullable(student).ifPresent(s -> System.out.println("年龄:" + s.getAge()));

如果对象不为空,则会打印这个年龄,因为内部已经做了NPE(非空判断),所以就不用担心空指针异常了

Optional.filter()方法(过滤对象)

filter()方法大致意思是,接受一个对象,然后对他进行条件过滤,如果条件符合则返回Optional对象本身,如果不符合则返回空Optional

public Optional<T> filter(Predicate<? super T> predicate) {Objects.requireNonNull(predicate);//如果为空直接返回thisif (!isPresent())return this;else//判断返回本身还是空Optionalreturn predicate.test(value) ? this : empty();
}

简单实例:

Student student = new Student();
student.setAge(18);
Optional.ofNullable(student).filter(s -> s.getAge()>10);

Optional.flatMap()方法(Optional对象进行二次包装)

public <U> Optional<U> map(Function<? super T, ? extends U>)

public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>>)

区别:flatMap处理函数的返回值是Optional包装的

map()方法将对应Optional< Funcation >函数式接口中的对象,进行二次运算,封装成新的对象然后返回在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));}
}

实例:

Student student = new Student();
student.setAge(18);
Optional<Object> optName = Optional.ofNullable(student).map(s -> Optional.ofNullable(s.getName()).orElse("name为空"));

Optional.orElse()方法(为空返回对象)

常用方法之一,这个方法意思是如果包装对象为空的话,就执行orElse方法里的value,如果非空,则返回写入对象

public T orElse(T other) {//如果非空,返回value,如果为空,返回otherreturn value != null ? value : other;
}

实例:

Student student = new Student();
student.setAge(18);
Optional.ofNullable(student).orElse(new Student("小明", 12));

Optional.orElseGet()方法(为空返回Supplier对象)

这个与orElse很相似,入参不一样,入参为Supplier对象,为空返回传入对象的.get()方法,如果非空则返回当前对象。推荐:Java面试题

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

实例:

Optional<Supplier<Student>> sup=Optional.ofNullable(Student::new);
//调用get()方法,此时才会调用对象的构造方法,即获得到真正对象
Optional.ofNullable(student).orElseGet(sup.get());

Suppiler是一个接口,是类似Spring的懒加载,声明之后并不会占用内存,只有执行了get()方法之后,才会调用构造方法创建出对象 创建对象的语法的话就是Supplier supStudent= Student::new; 需要使用时supStudent.get()即可

Optional.orElseThrow()方法(为空返回异常)

方法作用的话就是如果为空,就抛出你定义的异常,如果不为空返回当前对象,在实战中所有异常肯定是要处理好的,为了代码的可读性

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

实例:

//简单的一个查询
Member member = memberService.selectByPhone(request.getPhone());
Optional.ofNullable(member).orElseThrow(() -> new ServiceException("没有查询的相关数据"));

相似方法进行对比分析

可能看到这,没用用过的话会觉得orElse()orElseGet()还有orElseThrow()很相似,map()和flatMap()好相似,不用着急,都是从这一步过来的,我再给大家总结一下不同方法的异同点 orElse()orElseGet()orElseThrow()的异同点

方法效果类似,如果对象不为空,则返回对象,如果为空,则返回方法体中的对应参数,所以可以看出这三个方法体中参数是不一样的 orElse(T 对象) orElseGet(Supplier < T >对象) orElseThrow(异常)

map()和orElseGet的异同点

方法效果类似,对方法参数进行二次包装,并返回,入参不同 map(function函数) flatmap(Optional< function >函数)

具体要怎么用,要根据业务场景以及代码规范来定义,下面可以简单看一下我在实战中怎用使用神奇的Optional。推荐:Java面试题

实战场景

场景1:在service层中 查询一个对象,返回之后判断是否为空并做处理

//查询一个对象
Member member = memberService.selectByIdNo(request.getCertificateNo());
//使用ofNullable加orElseThrow做判断和操作
Optional.ofNullable(member).orElseThrow(() -> new ServiceException("没有查询的相关数据"));

场景2:我们可以在dao接口层中定义返回值时就加上Optional

public interface LocationRepository extends JpaRepository<Location, String> {Optional<Location> findLocationById(String id);
}

然在是Service中

public TerminalVO findById(String id) {//这个方法在dao层也是用了Optional包装了Optional<Terminal> terminalOptional = terminalRepository.findById(id);//直接使用isPresent()判断是否为空if (terminalOptional.isPresent()) {//使用get()方法获取对象值Terminal terminal = terminalOptional.get();//在实战中,我们已经免去了用set去赋值的繁琐,直接用BeanCopy去赋值TerminalVO terminalVO = BeanCopyUtils.copyBean(terminal, TerminalVO.class);//调用dao层方法返回包装后的对象Optional<Location> location = locationRepository.findLocationById(terminal.getLocationId());if (location.isPresent()) {terminalVO.setFullName(location.get().getFullName());}return terminalVO;}//不要忘记抛出异常throw new ServiceException("该终端不存在");
}

实战场景还有很多,包括return时可以判断是否返回当前值还是跳转到另一个方法体中,其它的还有很多。

Optional使用注意事项

Optional真么好用,真的可以完全替代if判断吗?我想这肯定是大家使用完之后Optional之后可能会产生的想法,答案是否定的 举一个最简单的栗子:

例子:如果我只想判断对象的某一个变量是否为空并且做出判断呢?

Person person=new Person();
person.setName("");
persion.setAge(2);
//普通判断
if(StringUtils.isNotBlank(person.getName())){//名称不为空执行代码块
}
//使用Optional做判断
Optional.ofNullable(person).map(p -> p.getName()).orElse("name为空");

我觉得这个例子就能很好的说明这个问题,只是一个很简单判断,如果用了Optional我们还需要考虑包装值,考虑代码书写,考虑方法调用,虽然只有一行,但是可读性并不好,如果别的程序员去读,我觉得肯定没有if看的明显。

Jdk 9对Optional优化

首先增加了三个方法: or()ifPresentOrElse() 和 stream()。or() 与orElse等方法相似,如果对象不为空返回对象,如果为空则返回or()方法中预设的值。

ifPresentOrElse() 方法有两个参数:一个 Consumer 和一个 Runnable。如果对象不为空,会执行 Consumer 的动作,否则运行 Runnable。相比ifPresent()多了OrElse判断。stream()将Optional转换成stream,如果有值就返回包含值的stream,如果没值,就返回空的stream。

来源:blog.csdn.net/weixin_45581915/article/details/124493863

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NASA宣布在火星上发现了3种有机分子

图来自美国国家航空航天局来源&#xff1a;海外网摘要&#xff1a;美国国家航空航天局&#xff08;NASA&#xff09;召开新闻发布会&#xff0c;公开了火星新发现——好奇号火星探测器在火星上发现了有机分子。当地时间周四&#xff08;7日&#xff09;&#xff0c;美国国家航空…

POJ 2255/递归:前序中序求后序

Sample Input DBACEGF ABCDEFG 已知二叉树的前序遍历与后序遍历求后序遍历 算法&#xff1a;前序遍历时&#xff0c;第一位为根&#xff1a;D&#xff1b;找到中序中的D&#xff0c;则前面的ABC在左子树&#xff0c;右边的EFG在右子树&#xff0c;则后序为为左子树右子树根:sol…

Chrome 爬虫插件 Web Scraper

Web Scraper 官网&#xff1a;https://webscraper.io/ 有关webscraper的问题&#xff0c;看这个就够了&#xff08;建议收藏&#xff09;&#xff1a; https://zhuanlan.zhihu.com/p/34104808https://blog.csdn.net/biggbang/article/details/86251526 web scraper 入门到精通…

AI新方向: 科学家们暂停模仿“人脑”,公布了新路线图

来源&#xff1a;华尔街新闻摘要&#xff1a;科学家们一直致力于创造一种像人类一样思考的机器&#xff0c;但经过一段时间的探索&#xff0c;这一进程遇到了阻碍&#xff0c;他们基本上已经暂停了模仿“人脑”&#xff0c;转而研究已有发现的应用。科学家们一直致力于创造一种…

C++ primer 4th 第10章《关联容器》总结

表10-1 关联容器类型 map 关联数组&#xff1a;元素通过键来存储和读取 set 大小可变的集合&#xff0c;支持通过键实现的快速读取 multimap 支持同一个键多次出现的map类型 multimap 支持同一个键多次出现的set类型 表10-2 pair类型提供的操作 pair<T1,T2> p1;…

强势~迷惑法应对

1、承认事实&#xff1b; 2、承认可能性&#xff1b; 3、原则上同意。 1、承认事实&#xff1b; 母亲&#xff1a;莎莉&#xff0c;你有很晚才回家。昨晚我到12点半&#xff0c;还给你打过电话呢。莎莉&#xff1a;是的&#xff0c;妈妈&#xff0c;昨晚我又回来得很晚。 2…

Hack.Chat 在浏览器里快速建立简单、随用即丢线上聊天室,无须下载安装软体

From&#xff1a;http://www.luoxiao123.cn/1554-6.html 有时候想跟其他使用者线上文字对话&#xff0c;但又不想把自己的联络资料&#xff08;例如 Facebook 或即时通讯帐号&#xff09;泄漏给对方&#xff0c;有些人可能会选择申请一个临时使用的帐号&#xff0c;但这未免也太…

CCAI2018 | 韩家炜:大规模文本数据挖掘的新方向

来源&#xff1a;中国人工智能学会现实中的大数据常常表示为一种非结构化&#xff0c;交叉和动态变化的文本数据。如何从大规模文本数据中抽取结构化知识是一个非常值得研究的任务。很多研究工作依赖于劳动密集型的数据标注&#xff0c;用有监督的方法去抽取知识。但是&#xf…

关于面试宝典中的各个问题(一)

1、关于浮点数1.0f在内存中的表示&#xff1a;是3f800000. 各个类型所占的字节数&#xff08;byte&#xff09;&#xff0c;1byte8bit char 1 short 2 bool 1 int 4 long 4 float 4 double 8 long double 8 char * 4 int * 4 float * 4 以上是对于我的电脑&#xff0c;在典型…

安卓手机 Python 自动化( uiautomation、uiautomation2、weditor )

其他自动化工具或者框架&#xff1a; Airtest&#xff1a;https://airtest.readthedocs.io/zh_CN/latest/autojs&#xff1a;Auto.js快速入门实战教程&#xff1a;https://zhuanlan.zhihu.com/p/90065914appium&#xff1a;https://blog.csdn.net/freeking101/article/details…

强势~否定决断法

否定决断法套路 对方&#xff1a;“你在......上做得不是很好”&#xff08;批评&#xff09;你&#xff1a;“你说得对。我在处理那个的时候不太机灵&#xff0c;对吗”&#xff08;否定决断法&#xff09; 示例一&#xff1a; 同事&#xff1a;“上周答应给的那份参考文档…

C++/C宏定义中## 连接符与# 符的含义

http://blog.163.com/wshyao126/blog/static/1070451420081018103237836/ ## 连接符与# 符 ## 连接符号由两个井号组成&#xff0c;其功能是在带参数的宏定义中将两个子串(token)联接起来&#xff0c;从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串(t…

揭秘|多伦多大学反人脸识别,身份欺骗成功率达99.5%

来源 &#xff1a;机器人大讲堂摘要&#xff1a;在一些社交媒体平台&#xff0c;每次你上传照片或视频时&#xff0c;它的人脸识别系统会试图从这些照片和视频中得到更多信息。比如&#xff0c;这些算法会提取关于你是谁、你的位置以及你认识的其他人的数据&#xff0c;并且&am…

安卓逆向_8 --- Android 调试工具 DDMS 和 Monitor ( 去掉 车来了 app 的广告 )

From&#xff1a;https://www.e-learn.cn/topic/3527658 Android SDK 中的 ddms 使用详解&#xff1a;https://blog.csdn.net/x83853684/article/details/80643131 ADB、Android Monitor、DDMS、HierarchyViewer、MAT、SysTrace、TraceView 性能分析工具使用大全&#xff1a;…

杂谈 | 微软复兴,它与苹果竟有这么多相似之处!

来源&#xff1a;网易智能摘要&#xff1a;且不要谈CEO们是否会让他们公司的“重生”&#xff0c;仅仅是成为一个成功帝国的好管家就已经是一项了不起的成就了。上周&#xff0c;微软市值超过了谷歌母公司Alphabet&#xff0c;成为继苹果&#xff08;Apple&#xff09;和亚马逊…

全能终端神器 --- MobaXterm 、开启 linux 远程桌面

From&#xff1a;https://cloud.tencent.com/developer/news/244102 官网地址&#xff1a;https://mobaxterm.mobatek.net MobaXterm 20.2_Professional.7z 下载地址&#xff1a;https://download.csdn.net/download/freeking101/12363312 MobaXterm 又名 MobaXVT&#xff0c…

强势~帮不了别人,也不用内疚

妻子的控诉 妻子&#xff1a;“你要是再让我生气&#xff0c;咱们就离婚。” 这种想法会让对方产生负疚感&#xff0c;因为言下之意是&#xff0c;婚约和两人之间的关系&#xff0c;要比夫妻双方的个人意愿和幸福更重要。 丈夫&#xff1a;“要是你确实觉得受不了&#xff0c…

【转】盛大创新院许式伟:影响我一生的五个重要选择

盛大创新院许式伟&#xff1a;影响我一生的五个重要选择 资料来源&#xff1a;http://www.programmer.com.cn/4206/ 作者&#xff1a; wuzhimin分类&#xff1a;坊间人语阅读&#xff1a;40,227 次添加评论文 / 许式伟 每个人的际遇是不同的&#xff0c;面临选择时&#xff0c;…

安卓逆向_7 --- 六种快速定位关键 Smali 代码的方法 ( 去掉 RE 广告 )

哔哩哔哩&#xff1a;https://www.bilibili.com/video/BV1UE411A7rW?p34 具体用法&#xff0c;看视频教程&#xff08; 去掉 RE 的 结束广告 &#xff09; 6 种定位关键代码的方法&#xff0c;当然还有其他方法&#xff0c;以后遇见了补充上&#xff1a; 1. 信息反馈法&#…

教机器遗忘或许比学习更重要:让AI健忘的三种方式

大数据文摘出品编译&#xff1a;臻臻、Shan LIU、龙牧雪大部分人不会喜欢遗忘的感觉。回到家顺手把钥匙丢在一个角落就再也想不起来放在哪儿了&#xff0c;街角偶遇一个同事却怎么拍脑袋也叫不出他的名字……我们害怕遗忘&#xff0c;讨厌遗忘。然而&#xff0c;生而为人&#…