java null替换_了不起的Java-Optional替代null处理

Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)。是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。

在这段代码就可能产生空异常;

String isocode =user.getAddress().getCountry().getIsocode().toUpperCase();//需要检查:

if (user != null) {

Address address=user.getAddress();if (address != null) {

Country country=address.getCountry();if (country != null) {

String isocode=country.getIsocode();if (isocode != null) {

isocode=isocode.toUpperCase();

}

}

}

}

Optional类的依赖依然还是函数接口那一套东西:

importjava.util.function.Consumer;importjava.util.function.Function;importjava.util.function.Predicate;import java.util.function.Supplier;

是要把面向接口编程走到底了。私有字段只有一个:

private final T value;

原生代码还是相当简单的:

public static Optionalempty() {

@SuppressWarnings("unchecked")

Optional t = (Optional) EMPTY;returnt;

}public static Optionalof(T value) {return new Optional<>(value);

}public static OptionalofNullable(T value) {return value == null ?empty() : of(value);

}public Optional map(Function super T, ? extends U>mapper) {

Objects.requireNonNull(mapper);if (!isPresent())returnempty();else{returnOptional.ofNullable(mapper.apply(value));

}

}

......

创建 Optional 包装实例

建空

Optional emptyOpt =Optional.empty();try{

Insurance obj=emptyOpt.get();

System.out.println("不为空");

}catch(NoSuchElementException ex) {

System.out.println("为空");

}

尝试访问 emptyOpt 变量的值会导致 NoSuchElementException,因为原声代码:

publicT get() {if (value == null) {throw new NoSuchElementException("No value present");

}returnvalue;

}

建可能为空(ofNullable不抛异常)

Optional opt = Optional.ofNullable(null);

不会异常

如此神奇,原因在于原生代码已经进行了判空,把私有value定成了empty(),这种不抛异常也会产生一个问题,那就是在消费实例的时候,还是要过滤掉空值。

public static OptionalofNullable(T value) {return value == null ?empty() : of(value);

}

建为空时抛异常(即of不可为空)

public static voidwhenCreateOfEmptyOptional_thenNullPointerException() {

Insurance ins= newInsurance();

Optional opt =Optional.of(ins);

ins=null;try{

opt=Optional.of(ins);

System.out.println("不为空");

}catch(NullPointerException ex) {

System.out.println("为空");

}

}

会进入异常。跟踪原生代码发现了原因:

public static T requireNonNull(T obj) {if (obj == null)throw newNullPointerException();returnobj;

}

访问 Optional 对象的值

get

从 Optional 实例中取回实际值对象的方法之一是使用 get() 方法:

@Testpublic voidwhenCreateOfNullableOptional_thenOk() {

String name= "John";

Optional opt =Optional.ofNullable(name);

assertEquals("John", opt.get());

}

这个方法会在值为 null 的时候抛出异常。要避免异常,你可以选择首先验证是否有值:

@Testpublic voidwhenCheckIfPresent_thenOk() {

User user= new User("john@gmail.com", "1234");

Optional opt =Optional.ofNullable(user);

assertTrue(opt.isPresent());

assertEquals(user.getEmail(), opt.get().getEmail());

}

ifPresent的使用

原生代码:

public void ifPresent(Consumer super T>consumer) {if (value != null)

consumer.accept(value);

}

只有当值不为空,才执行消费者方法accept,这是比较安全的。

public static voidprintName(Insurance obj)

{

Optional.ofNullable(obj).ifPresent(u-> System.out.println("The name is : " +u.getName()));

}

Insurance obj= newInsurance();

obj.setName("张三");

Insurance objNull= null;

printName(obj);

printName(objNull);//输出:The name is : 张三

isPresent的使用

感觉有了ifPresent,不需要再用isPresent来判断空了,否则感觉非常啰嗦。

orElse的使用

在对象为空的时候返回默认值。它的工作方式非常直接,如果有值则返回该值,否则返回传递给它的参数值。

Insurance obj = newInsurance();

obj.setName("张三");

Insurance objNull= null;

Insurance result=Optional.ofNullable(objNull).orElse(obj);

System.out.println(obj.hashCode());

System.out.println(result.hashCode());

result实际是返回的obj,而不是null。

filter的使用

filter()方法接受参数为Predicate对象,用于对Optional对象进行过滤,如果符合Predicate的条件,返回Optional对象本身,否则返回一个空的Optional对象

public static voidfilterAge(Student student)

{

Optional.ofNullable(student).filter( u-> u.getAge() > 18).ifPresent(u -> System.out.println("The student age is more than 18."));

}

map的使用

map()方法的参数为Function(函数式接口)对象,map()方法将Optional中的包装对象用Function函数进行运算,并包装成新的Optional对象(包装对象的类型可能改变)

原生代码:

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

Objects.requireNonNull(mapper);if (!isPresent())returnempty();else{returnOptional.ofNullable(mapper.apply(value));

}

}

下面代码中,先用ofNullable()方法构造一个Optional对象,然后用map()计算学生的年龄,返回Optional对象(如果student为null, 返回map()方法返回一个空的Optinal对象)

public static OptionalgetAge(Student student)

{return Optional.ofNullable(student).map(u ->u.getAge());

}

flatMap的使用

跟map()方法不同的是,入参Function函数的返回值类型为Optional类型,而不是U类型,这样flatMap()能将一个二维的Optional对象映射成一个一维的对象,

总而言之,map进去是什么,出来维度不变,flatMap是为了拍扁结果。

public Optional flatMap(Function super T, Optional>mapper) {

Objects.requireNonNull(mapper);if (!isPresent())returnempty();else{returnObjects.requireNonNull(mapper.apply(value));

}

}//例子

Optional nonEmptyGender = Optional.of("male");

Optional emptyGender =Optional.empty();

System.out.println("Non-Empty Optional:: " +nonEmptyGender.map(String::toUpperCase));

System.out.println("Empty Optional :: " +emptyGender.map(String::toUpperCase));

Optional> nonEmptyOtionalGender = Optional.of(Optional.of("male"));

System.out.println("Optional value :: " +nonEmptyOtionalGender);

System.out.println("Optional.map :: " + nonEmptyOtionalGender.map(gender ->gender.map(String::toUpperCase)));

System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase)));

封装可能的空值

使用ofNullable,比如在一些map中的key为空的情况下使用:

Optional opt = Optional.ofNullable(map.get("someNullKey"));

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值