Java中的Optional类用法详细讲解
java中尝试访问空引用的属性调用空引用的方法是会报空指针NullPointerException异常。实际项目中会处理大量为空的值,代码会有很多的条件判断,难以阅读与维护。
为何要用 Optional
java中尝试访问空引用的属性调用空引用的方法是会报空指针NullPointerException异常。实际项目中会处理大量为空的值,代码会有很多的条件判断,难以阅读与维护。
一、Optional定义
Optional类引入了一种显式的方式来处理可能为空的对象,强制程序员在可能为空的情况下进行显式的处理,以避免空指针异常。
Optional类似容器,可以包含各种类型的值,也可以为null。Optional类提供了一系列方法来方便地操作内部的值。常用的方法有get、orElse、orElseGet、orElseThrow等。
Optional的设计也考虑了函数式编程的原则,可以与Lambda表达式和StreamAPI等特性结合使用,可以进行链式调用替代命令式编程的方式通过编写if条件语句检查null值。
二、Optional对象的方法
首先我们需要创建两个类,User类与UserRepository类。
User类
UserRepository类
1.isPresent、isEmpty方法
isPresent方法用于检查optional内是否存在值,返回为布尔值,存在为true,不存在为false。
isEmpty方法用于检查optional内是否为空,返回为布尔值,为空为true,不为空为false。
返回值为false与true。
2.empty、of、ofNullable方法
若创建的对象为null,则可以采用empty()方法。
创建不为null的对象需要调用of方法,此时若value为null,则抛出NullPointerException异常。
若想要创建可能为null的对象,可以使用ofNullable( )方法。
3.get、orElse、orElseGet与orElseThrow方法
取值可以使用get()方法,若取值对象为null,会报java.util.NoSuchElementException异常(并非java.lang.NullPointerException异常)。
我们这里修改UserRepository类中的findUserByName方法,使其返回值为Optional对象。
orElse是Optional类中的一个重要方法,它用于获取值或在值为空的情况下提供一个默认值。
orElse方法即使读到的数据不为null,仍会创建一个新User对象。因此最好使用只有读到的数据为null的时候才会新建对象的orElseGet方法。
orElseGet方法的参数为Supplier的函数式接口,需要使用Lambda表达式实现。
orElseThrow方法用于在 Optional 对象中的值为空时抛出一个指定的异常。
orElseThrow方法通过Supplier的函数式接口,可以生成自定义异常,默认抛出异常为java.util.NoSuchElementException。
4.ifPresent、ifPresentOrElse、filter方法
ifPresent方法参数中若对象不为null,则会执行Labmda中的方法;
若参数对象为null,则不会执行Labmda中的方法,也不会报错。
当我们希望值为空时进行其他操作,需要使用ifPresentOrElse方法。
若满足filter方法中的条件,则会返回包含值的Optional对象,如果不满足,则返回空的Optional对象
OPtionals<User> op=optionalUser.filter(user->user.getFullName().equals("Peter parker"));
sout(op.isPresent());
5.Map与flatMap方法
进行两个方法前需要将User类中的 getFullName方法返回值修改为Optional。
map方法:对Optional中的值进行转换(若值为空,则map方法什么也不会做,直接返回空的Optional对象)。
这个变换基于提供该map的函数,并且这个变换是可选的,如果optional的值为空则不会做任何改变,并且map方法不会改变原始的Optional对象,而返回新的Optional对象,因此可以链式调用进行多个转换操作。
flatmap方法用于扁平化嵌套的Optional结构,以避免引入不必要的嵌套层级,具体为flatmap的转换函数返回的必须是另一个Optional对象,意味着flatMap方法可以用于嵌套的Optional情况,可以将两个为嵌套关系的Optional对象转换为一个。如果原始的Optional对象为空,或转换函数返回的Optional对象为空,那么最终得到的也是为空的Optional对象。
若只需要对Optional对象中的值进行转换,而不需要嵌套的Optional,那么使用map方法更合适
如果要进行一些操作返回另外一个Optional对象,flatmap方法更合适。
6.Stream方法
Optional的stream方法,可以将Optional对象转换为Stream对象,对其中的值进行流操作,如果Optional对象包含值,则将这个值封装到一个Stream流中,如果Optional对象为空,则创造一个为空的Stream流
三、不适合使用Optional对象的情况
不应该用于类的字段,会增加内存消耗,并使序列化变得复杂;
不应该用于方法参数,使方法的理解和使用变得复杂;
不应用于构造器参数,迫使调用者创建Optional实例,应该通过构造器重载解决;
不应该用于集合的参数,集合已经很好的处理空集合的情况,没必要使用Optional包装集合;
不建议使用get方法,若为null会报错。
四、以下是如何处理和避免Java8 Optional错误的一些建议:
在使用get()方法之前,一定要使用isPresent()方法检查Optional对象是否存在。
不要使用isPresent()方法和orElse()方法。而应该使用orElseGet()方法,让程序只在需要时才执行Supplier。
不要将Optional作为类的字段或方法的参数。这会导致类或方法变得混乱且难以维护。尽可能将Optional用于返回值,只在有需要时才将其用于参数。
避免在递归方法中使用Optional。在Java中递归是简洁明了的,但在递归方法中使用Optional 会导致程序的性能大幅下降。
更多推荐
所有评论(0)