“ 在前面我们已经谈论过Java8的Lambda表达式,方法引用,Stream。除了这些之外Java8中还有一个很重要的知识:Optional ”
在这篇文章的开始,首先来说一下Java8中有哪些新特性(本该第一篇就说到的):Lambda 表达式 ,方法引用,默认方法(在接口里面有了一个实现的方法),新工具(新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps),Stream API,Date Time API(加强对日期与时间的处理),Optional 类,Nashorn和JavaScript 引擎(Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用)
那么今天我们就来谈一谈Optional 类,通常来说它是用来解决空指针异常的。在它的源码注释上有这么一段话:
A container object which may or may not contain a non-null value. 一个容器对象,该对象可以包含或不包含非空值
也就说:Optional提供的方法,我们就不用显式进行空值检测。
这篇文章将有下面几个模块:
1.Optional方法介绍
2.Optional使用例子
3.Optional注意事项
01
—
Optional方法介绍
我们首先来看一下Optional这个类有哪些方法:
1.boolean isPresent()
如果值存在则方法会返回true,否则返回 false。
2.T get()
如果在这个Optional中包含这个值,返回值,否则抛出异常: NoSuchElementException
3.static <T> Optional<T> empty()
返回空的 Optional 实例。
4.boolean equals(Object obj)
判断其他对象是否等于 Optional。
5.Optional<T> filter(Predicate<? super <T> predicate)
如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
6.<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)
如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
7.int hashCode()
返回存在值的哈希码,如果值不存在 返回 0。
8.void ifPresent(Consumer<? super T> consumer)
如果值存在则使用该值调用 consumer , 否则不做任何事情。
9.<U>Optional<U> map(Function<? super T,? extends U> mapper)
如果存在该值,提供的映射方法,如果返回非null,返回一个Optional描述结果。
10.static <T> Optional<T> of(T value)
返回一个指定非null值的Optional。
11.static <T> Optional<T> ofNullable(T value)
如果为非空,返回 Optional 描述的指定值,否则返回空的 Optional。
12.T orElse(T other)
如果存在该值,返回值, 否则返回 other。
13.T orElseGet(Supplier<? extends T> other)
如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果
14.<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
15.String toString()
返回一个Optional的非空字符串,用来调试
对于上面的方法,有一些是不是很眼熟啊?比如of(),filter(),map(),flatmap()。这些方法跟我们前面用到的方法是一个东西吗?
这里就说明一下:他们不是一样的东西,首先前面我们用到的这些方法返回的对象是Stream,这里的方法返回的对象是Optional。大家不要混淆哦!
看完了这些方法我们再看例子吧,通过例子大家就能很好的理解这个类了
02
—
Optional使用举例
下面的代码上面标清了注释,我们就从这上面来一步步看吧,为了方便测试,我的参数用了String类型,我们可以通过传递字符串和null来看效果:
public static void optinalMethod(String everyDayJava) {
//@throws NullPointerException if value is null
//如果值是null 抛出空指针异常
Optional<String> optional =
Optional.of("Java8新特性Optinal");
/* is non-null, otherwise an empty {@code Optional}
如果值是null 返回一个为空的Optional对象
和上面对比一下:
第一种为什么还会存在:如果确定对象不为null,
为什么还要判断一下呢,这增加了开销。
如果我们在别的地方需要知道这个对象是否为null,
使用ofNullable去隐藏这个异常显然也是不合理的
*/
Optional<String> optional2 =
Optional.ofNullable("Java8新特性Optinal");
/*
orElse(T other) :
@return the value, if present, otherwise {@code other}
orElse(T other):
如果value存在返回value, 否则返回other
*/
String optional3 =
Optional.ofNullable(everyDayJava)
.orElse("每天学Java放弃了学习Java");
System.out.println(optional3);
/*
orElseGet方法可以接受Supplier接口的实现用来生成默认值
*/
String optional4 =
Optional.ofNullable(everyDayJava)
.orElseGet(OptinalTest::get);
System.out.println(optional4);
/*
看到结果之后是不是觉得有点意思啊,
不用再像以前那样去走一系列的判断了,
而且这样很流畅啊
*/
/*
map:
*/
String opeional5 =
Optional.ofNullable(everyDayJava)
.map(n -> n.toLowerCase())
.orElse("我要小写英文");
System.out.println(opeional5);
/*
flatMap方法与map方法类似,
区别在于mapping函数的返回值不同。
map方法的mapping函数返回值可以是任何类型T,
而flatMap方法的mapping函数必须是Optional。
*/
String opeional6 =
Optional.ofNullable(everyDayJava)
.flatMap(n -> Optional.of(n.toLowerCase()))
.orElse("我要要flatmap小写英文");
System.out.println(opeional6);
/*
filter个方法通过传入限定条件对Optional实例的值进行过滤。文档描述如下:
*/
String opeional7 =
Optional.ofNullable(everyDayJava)
.filter(n -> {
return n.length() > 10;
}).orElse("长度不足10");
System.out.println(opeional7);
}
main方法
public static void main(String[] args) {
optinalMethod("每天学Java也在一直学习Java");
optinalMethod(null);
}
输出结果(同步的,所以不要交叉着看,前面输出的是第一次调用,后面输出的是第二次调用):
Connected to the target VM, address: '127.0.0.1:50578', transport: 'socket'
每天学Java也在一直学习Java
每天学Java也在一直学习Java
每天学java也在一直学习java
每天学java也在一直学习java
每天学Java也在一直学习Java
-----------------------
每天学Java放弃了学习Java
hello
我要小写英文
我要要flatmap小写英文
长度不足10
Disconnected from the target VM, address: '127.0.0.1:50578', transport: 'socket'
03
—
Optional注意事项
首先我们知道Optional是解决null安全问题的一个API
然后是安全的链式调用,而不是一层层判断了,它摒弃以前需要大量的非空判断模板代码。
最后注意的是:
1) Optional应该只用处理返回值,而不应该作为类的字段或者方法的参数.因为这样会造成额外的复杂度.
2) 使用Option应该避免直接适应构造器和get,而应该使用isElse的系列方法避免频繁的非空判断
3) map和flatMap要注意区分使用场景
那就来一句话做个小结: 使用 Optional 时尽量不直接调用 Optional.get() 方法,Optional.isPresent() 更应该被视为一个私有方法,应依赖于其他像 Optional.orElse(), Optional.orElseGet(), Optional.map() 等这样的方法
那么今天的Optional的分享就到这里结束了哦。
跟小伙伴们分享一下这一周的推送安排,大家可以重点关注自己喜欢的文章(已经发布的大家可以直接点击链接进去哦):
九月10号周一:探究Java8的Stream(一)
九月11号周二:探究Java8的Stream(二)
九月12号周三:关系型数据库之oracle
九月13号周四:探究Java8的Optional 类
九月14号周五:Effective Java(第三版)——条目十四:考虑实现Comparable接口
那么今天小程序更新的题库是什么呢?
今天小程序更新的题目是:
1.你知道MySQL的查询缓存吗?
2.如何开启Mysql查询缓存
3.什么样的语句Mysql不会去缓存
4.MySQL查询缓存的优缺点是什么?
5.Mysql的查询语句增加什么关键字会避开缓存呢