更优雅的判空 - Optional类的使用

1.用处

Optional 类是 Java 8 引入的一个特性。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException),使用它可以避免代码中出现过多的 if (obj != null) { } 这样范式的代码,支持链式编程。

引入:在项目中,经常会遇见需要取出一个处于很深的结构的实体中的某个值,比如

System.out.println(student.getAddress().getCity().getCityName());

如果想要成功无异常的取出需要的cityName的值,需要在访问每一个值之前对其进行判空,这就需要使用 if…{} 的结构,起码需要判断三次,嵌套三层 if…{} 会使得代码非常冗余。而Optional就可以很明显的简化这个过程,实力代码如下:

//直接放入进行一步步的取值即可,不会抛出异常
String cityName = Optional.ofNullable(student)
				.map(s -> s.getAddress())
				.map(s -> s.getCity())
				.map(s -> s.getCityName())
                  //如果有节点为空,则会打印该值
				.orElse("该值,或者前置节点的值为空");
//如果无节点为空,就打印它真实的值;有节点为空就打印 “该值,或者前置节点的值为空”
System.out.println(cityName);

使用Optional可以简化代码,此外它还提供其他的api方法可供调用;

2.创建使用

Optional实际上是将需要处理的实体转化成一个容器对象,然后再对容器进行处理;而将实体转化为容器对象有三种方法:

  • Optional.of(obj):它要求传入的 obj 不能是 null 值的, 否则直接报NullPointerException 异常。
  • Optional.ofNullable(obj):它以一种智能的,宽容的方式来构造一个 Optional 实例。来者不拒,传 null 进到就得到 Optional.empty(),非 null 就调用 Optional.of(obj)
  • Optional.empty():返回一个空的 Optional 对象

可以根据不同的情况分别使用;

使用原则:

1、避免使用Optional.isPresent()来检查实例是否存在,因为这种方式和null != obj没有区别,这样用就没什么意义了。

2、避免使用Optional.get()方式来获取实例对象,因为使用前需要使用Optional.isPresent()来检查实例是否存在,否则会出现NoSuchElementException异常问题。所以使用orElse(),orElseGet(),orElseThrow()获得你的结果。

3、尽量使用orElseGet(),因为这个方法只有在传值为空的时候才会执行括号中的函数,而orElse()不管传值是什么,都会执行

括号中的函数,造成资源浪费。

3.常用函数

① isPresent() 如果值存在返回true,否则返回false

它有两个重载方法,一个无入参,只是判断传入的容器是否有值;一个支持一个消费类型函数入参,如果传入容器有值就执行函数,否则不做任何操作;

// 返回student 
Student student = createBody();

//无入参方法:判断对象的值是否存在
boolean present = Optional.ofNullable(student).map(s->s.getName()).isPresent();
System.out.println(present ? "不为空" : "为空");
//消费类型函数入参方法:如果值存在就直接打印,不存在就不执行 ifPresent() 
Optional.ofNullable(student)
		.map(s->s.getName())
		.ifPresent(s-> System.out.println(s));

返回结果

// ① 返回student 为null时
null
为空
// ② 返回student 都有值时
Student(name=张三, age=18, address=null)
不为空
张三   

② orElse() 如果有值则将其返回,否则返回指定的其它值

orElse() 与 orElseGet() 返回一致,区别在于 orElse() 不管传值是否为空都会先执行括号内函数,而 orElseGet() 只会在传值为空的情况下执行,因此一般推荐使用 orElseGet() 进行处理。

还有一个orElseThrow() 该方法是有值则将其返回,没有值将返回指定的异常;

代码举例:

Student student = createBody();
//不报错
System.out.println(student);
//不管传值是否为空都会先执行括号内函数
String s1 = Optional.ofNullable(student)
			.map(s -> s.getName())
			.orElse(returnDeault());
System.out.println(s1);
//传值为空的情况下才执行
String s2 = Optional.ofNullable(student)
			.map(s -> s.getName())
			.orElseGet(() -> returnDeault());
System.out.println(s2);
//传值为空的话会抛出指定异常
String s3 = Optional.ofNullable(student)
			.map(s -> s.getName())
			.orElseThrow(() -> new MyException("学生姓名为空"));
System.out.println(s3);

    /**
    * 方法
    */
	public String returnDeault() {
		System.out.println("执行了returnDeault方法");
		return "未知";
	}

返回值:

//① 返回student 为null时,orElse()跟orElseGet()都会执行
null
执行了returnDeault方法
未知
执行了returnDeault方法
未知
throw new MyException("学生姓名为空")// --抛出异常
//② 返回student 都有值时,只有orElse()会执行,orElseGet()不再执行
Student(name=张三, age=18, address=null)
执行了returnDeault方法
张三
张三
张三

③ filter() 如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional

Student student = createBody();
System.out.println(student);

Student student2 = Optional.ofNullable(student)
		.filter(s -> s.getName() != null)
		.orElseGet(()->{return new Student().setName("手动创建!");});
System.out.println(student2);

返回值:

//① 返回student 为null时,该值被过滤掉,转而返回 orElseGet() 创造的student
null
Student(name=手动创建!, age=null, address=null)
//② 返回student 都有值时,返回真实值
Student(name=张三, age=18, address=null)
Student(name=张三, age=18, address=null)

④ map() 如果有值,则对其执行调用mapping函数得到返回值,否则返回空Optional

上面例子中已使用过

Student student = createBody();
System.out.println(student);

String s1 = Optional.ofNullable(student)
			.map(s -> s.getName())
			.orElseGet("未知"::toString);
System.out.println(s1);

返回值

// 返回值为空
null
未知
// 返回值不为空
Student(name=张三, age=18, address=null)
张三

⑤ flatMap() 不自动封装的 map()

map和flatMap均要求optional对象非空才执行mapper方法,二者均返回Optional对象。

但是map会自动将计算结果封装为Optional对象,而flatMap需要自己进行封装。

举例

Student student = createBody();
System.out.println(student);

Optional<String> s1 = Optional.ofNullable(student)
			.map(s -> s.getName()); //map() 的函数的返回值直接就可以是值的类型
Optional<String> s = Optional.ofNullable(student)
			.flatMap(student1 -> Optional.ofNullable(student1.getName()));//flatMap() 的函数返回值需要处理一下
System.out.println(s1);

返回值一致,不再展示

– 完结 –

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OptionalJava 8中引入的一个用于处理可能为空的对象的。它提供了一种优雅的方式来判断对象是否为空,并且可以避免使用丑陋的空指针检查代码。\[3\] 在引用\[1\]和引用\[2\]的代码示例中,通过将需要判空的对象转换为Optional对象,我们可以使用Optional的方法来进行判空操作。例如,使用map方法可以获取对象的某个属性,然后使用filter方法进行条件过滤,最后使用ifPresent方法来执行某个操作。如果对象为空或者不满足条件,这些操作都不会执行。\[1\]\[2\] 通过使用Optional,我们可以加清晰和简洁地判断对象是否为空,避免了繁琐的空指针检查。这种写法使代码加可读性和可维护性。\[3\] #### 引用[.reference_title] - *1* *2* [使用Optional进行判空操作](https://blog.csdn.net/zx123456_6838499/article/details/129912331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Java如何进行优雅判空——Optional的灵活应用](https://blog.csdn.net/qq_42102911/article/details/129025220)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值