Java 8 引入的 Optional类。主要用来解决空指针异常(NullPointerException)
,空指针异常是导致Java应用程序失败的最常见原因。
Optional类可以理解为一个容器:它既可以保存类型T的对象,也可以保存null。
Optional类提供了很多有用的方法,并实现了检查空值的功能,程序员就不用显式地写空值检测的代码,再结合函数式编程,使得代码更加干净,简洁。
Optional类可以理解为一个容器:它既可以保存类型 T的对象,也可以保存 null。
of:为非null的值创建一个optional,如果传入为null,则会空指针。
@Test public void testOf(){ JUser jUser = new JUser(); jUser.setId(100L); jUser.setUsername("赵云"); jUser.setPazzword("abc123"); jUser.setHeight(1.78D); jUser.setBirthday(new Date()); jUser.setStatus(JUserStatusEnum.ACTIVATE); Optional<JUser> optionalJUser = Optional.of(jUser); System.out.println(optionalJUser.get()); // 输出结果:jUser信息 jUser = null; Optional<JUser> optionalJUser2 = Optional.of(jUser); System.out.println(optionalJUser2.get()); // 输出结果:java.lang.NullPointerException }
ifNullable:为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
@Test public void testOfNullable(){ JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); System.out.println(optionalJUser); // 输出结果:Optional.empty JUser jUser1 = optionalJUser.get();// 输出结果:在这一行报错啦,java.lang.NullPointerException: No value present }
empty:返回一个空 Optional实例。
注意: Optional.empty() 所有保存 null包装成的 Optional对象,而且是单例模式
的。与泛型无关。
@Test public void testEmpty(){ Optional<Object> empty = Optional.empty(); System.out.println(empty); // 输出结果:Optional.empty Object o1 = Optional.<Integer>empty(); Object o2 = Optional.<String>empty(); System.out.println(o1 == o2);// 输出结果:true }
isPrensent:如果值存在返回true,不存在返回false。
@Test public void testIsPresent(){ JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); boolean present = optionalJUser.isPresent(); System.out.println(present); // 输出结果:false }
ifPresent:接受一个Consumer参数,如果对象不为空,就调用consumer接口。否则不做处理。
@Test public void testIfPresent(){ JUser jUser = new JUser(); jUser.setId(100L); jUser.setUsername("赵云"); jUser.setPazzword("abc123"); jUser.setHeight(1.78D); Optional<JUser> optionalJUser = Optional.ofNullable(jUser); optionalJUser.ifPresent(u -> { // 不为 null时才会执行断言 System.out.println(u);// 输出结果:jUser信息 }); }
get:如果有值则返回,没有值抛出NoSuchElementException异常
@Test public void testGet(){ JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); // JUser jUser1 = optionalJUser.get(); // 输出结果:java.lang.NullPointerException // 可以使用 isPresent方法检查 if(optionalJUser.isPresent()){ System.out.println(optionalJUser.get());// 输出结果:此时为空,不执行该语句 } }
orElse(T other):如果保存的值不是null,则返回原来的值,否则返回 other。
@Test public void testOrElse(){ JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); JUser jUser1 = optionalJUser.orElse(new JUser()); System.out.println(jUser1);// 输出结果:jUser实例的默认信息 // JUser{id=null, username='null', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null} }
orElseGet(Supplier<? extends T> other):
如果保存的值不是null,则返回原来的值,否则调用 生产者函数 并返回调用结果的。
@Test public void testOrElseGet(){ JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); JUser jUser1 = optionalJUser.orElseGet(() -> { JUser u = new JUser(); u.setId(100L); u.setUsername("赵云"); return u; }); System.out.println(jUser1);// 输出结果:u实例信息 // JUser{id=100, username='赵云', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null} }
注意:orElse和orElseGet方法的区别
orElseThrow(Supplier<? extends X> exceptionSupplier):有值返回,没有值抛出supplier接口创建的异常
@Test public void testOrElseThrow(){ JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); JUser jUser1 = optionalJUser.orElseThrow(() -> { return new RuntimeException("testOrElseThrow "); }); // 输出结果:java.lang.RuntimeException: testOrElseThrow }
map(Function<? super T,? extends U> mapper):
有值,就调用 Function函数并返回生成的值。否则返回空的optional。
@Test public void testMap(){ JUser jUser = new JUser(); jUser.setId(100L); jUser.setUsername("赵云"); Optional<JUser> optionalJUser = Optional.ofNullable(jUser); Optional<JUser> optionalJUser1 = optionalJUser.map((u) -> { u.setId(u.getId() + 100L); u.setUsername("赵云2"); return u; }); System.out.println(optionalJUser1.get());// 输出结果:JUser{id=200, username='赵云2', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null} // 如果 jUser= null,则输出结果:java.lang.NullPointerException }
flatMap(Function<? super T, ? extends Optional<? extends U>> mapper):
它map类似,区别在于他调用结束的时候,不会对optional做一个封装
@Test public void testFlatMap() { JUser jUser = new JUser(); jUser.setId(100L); jUser.setUsername("赵云"); Optional<JUser> optionalJUser = Optional.ofNullable(jUser); Optional<JUser> optionalJUser1 = optionalJUser.flatMap((u) -> { //需要我们自己的去封装一个Optional u.setId(u.getId() + 100L); u.setUsername("赵云2"); return Optional.of(u); }); System.out.println(optionalJUser1.get());// 输出结果:JUser{id=200, username='赵云2', pazzword='null', age=null, age2=0, sex=null, height=null, height2=0.0, birthday=null, status=null} // 如果 jUser= null,则输出结果:java.lang.NullPointerException }
filter:有值,返回满足条件的optional。否则返回空的optional
@Test public void testFilter() { JUser jUser = new JUser(); jUser.setId(100L); jUser.setUsername("赵云"); Optional<JUser> optionalJUser = Optional.ofNullable(jUser); // 没有满足的,返回空的Optional Optional<JUser> optionalJUser1 = optionalJUser.filter(u -> { return u.getId() == 1; }); System.out.println(optionalJUser1.get());// 输出结果:java.util.NoSuchElementException: No value present }
上面介绍了 Java 8 的特性,Java 9 为 Optional 类添加了三个方法:
or() 方法与 orElse() 和 orElseGet() 类似,它们都在对象为空的时候提供了替代情况。
or() 的返回值是由 Supplier 参数产生的另一个 Optional 对象。
@Test public void testOr() { JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); Optional<JUser> optionalJUser1 = optionalJUser.or(() -> { JUser u = new JUser(); u.setId(100L); u.setUsername("赵云"); return Optional.of(u); }); System.out.println(optionalJUser1.get());// 输出结果:u信息 }
ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction):
如果对象包含值,会执行 Consumer 的动作,否则运行 Runnable。
@Test public void testIfPresentOrElse() { JUser jUser = null; Optional<JUser> optionalJUser = Optional.ofNullable(jUser); optionalJUser.ifPresentOrElse(u -> System.out.printf("user id = {}" + u.getId()), () -> System.out.printf("User not found")); // 输出结果:User not found }
stream() 方法,它通过把实例转换为 Stream 对象,让你从广大的 Stream API 中受益。如果没有值,它会得到空的 Stream;有值的情况下,Stream 则会包含单一值。
@Test public void testStream() { JUser jUser = new JUser(); jUser.setId(100L); jUser.setUsername("赵云"); List<JUser> jUserList = Optional.ofNullable(jUser) .stream() .filter(u -> u.getId() == 100) .map(u -> { u.setId(u.getId() + 100L); u.setUsername("赵云2"); return u; }) .collect(Collectors.toList()); System.out.println(jUserList);// 输出结果:数据 }
总结:
Optional 是 Java 语言的有益补充 —— 它旨在减少代码中的 NullPointerExceptions,虽然还不能完全消除这些异常。
它也是精心设计,自然融入 Java 8 函数式支持的功能。
总的来说,这个简单而强大的类有助于创建简单、可读性更强、比对应程序错误更少的程序。
参考文章:
– 求知若饥,虚心若愚。