为了解决空指针异常
//Pre-Java 8 if(str!=null){ System.out.println(str); } //Java 8 Optional.ofNullable(str).ifPresent(System.out::println);
- Optional实际上是一个容器,可以保存任意类型的值,或者仅保存null。Optional提供很多有用的方法,这样我们就不用显示进行空指针检测。
- 它比if语句好在代码可读性更好,而且它提供的是编译时检测,能极大的降低NPF。
Optional.of()或者Optional.ofNullable():创建Optional对象,差别在于of不允许参数是null,返回一个包含参数的Optional对象;而ofNullable则无限制,为null则返回一个不包含值的Optional对象(底层是根据参数为null否来选择调用of()/empty()。
// 参数不能是null Optional<Integer> optional1 = Optional.of(1); // 参数可以是null Optional<Integer> optional2 = Optional.ofNullable(null); //返回null // 参数可以是非null Optional<Integer> optional3 = Optional.ofNullable(2);
Optional.empty():返回一个不包含值的Optional对象:
Optional<Integer> optional1 = Optional.ofNullable(null); Optional<Integer> optional2 = Optional.ofNullable(null); System.out.println(optional1 == optional2);// true System.out.println(optional1 == Optional.<Integer>empty());// true Object o1 = Optional.<Integer>empty(); Object o2 = Optional.<String>empty(); System.out.println(o1 == o2);// true
isPresent():判断值是否存在
Optional<Integer> optional1 = Optional.ofNullable(1); Optional<Integer> optional2 = Optional.ofNullable(null); // isPresent判断值是否存在 System.out.println(optional1.isPresent() == true); System.out.println(optional2.isPresent() == false);
ifPresent(Consumer consumer):如果option对象保存的值不是null,则调用consumer对象,否则不调用(调用指的是重写Consumer接口的方法,重写了什么内容就照着执行)
Optional<Integer> optional1 = Optional.ofNullable(1); Optional<Integer> optional2 = Optional.ofNullable(null); // 如果不是null,调用Consumer optional1.ifPresent(new Consumer<Integer>() { @Override public void accept(Integer t) { System.out.println("value is " + t); } }); // null,不调用Consumer optional2.ifPresent(new Consumer<Integer>() { @Override public void accept(Integer t) { System.out.println("value is " + t); } });
orElse(value):如果optional对象保存的值不是null,则返回原来的值,否则返回value
Optional<Integer> optional1 = Optional.ofNullable(1); Optional<Integer> optional2 = Optional.ofNullable(null); // orElse System.out.println(optional1.orElse(1000) == 1);// true System.out.println(optional2.orElse(1000) == 1000);// true
orElseGet(Supplier supplier):功能与orElse一样,只不过orElseGet参数是一个对象
Optional<Integer> optional1 = Optional.ofNullable(1); Optional<Integer> optional2 = Optional.ofNullable(null); System.out.println(optional1.orElseGet(() -> { return 1000; }) == 1);//true System.out.println(optional2.orElseGet(() -> { return 1000; }) == 1000);//true
orElseGet(Supplier supplier):功能与orElse区别在于,orElseGet()传入的参数为一个Supplier接口的方法重写,当Optional中有值时,返回值;否则返回从Supplier获得的值。
Optional<Integer> optional1 = Optional.ofNullable(1); Optional<Integer> optional2 = Optional.ofNullable(null); System.out.println(optional1.orElseGet(() -> { return 1000; }) == 1);//true System.out.println(optional2.orElseGet(() -> { return 1000; }) == 1000);//true
orElseThrow():值不存在则抛出异常,存在则什么不做。好处在于我们可以决定抛出什么样的异常,而不总是NPE。用途举例:查询某个实体时,如果数据库中不存在该记录就可以抛出EntityNotFoundException,处理EntityNotFoundException的方法中我们可以给客户端返回404状态码和异常信息。
Optional<Integer> optional1 = Optional.ofNullable(1); Optional<Integer> optional2 = Optional.ofNullable(null); optional1.orElseThrow(()->{throw new IllegalStateException();}); try { // 抛出异常 optional2.orElseThrow(()->{throw new IllegalStateException();}); } catch(IllegalStateException e ) { e.printStackTrace(); }
filter(Predicate):判断Optional对象中保存的值是否满足Predicate,是则返回原来的Optional对象,否则返回空的Optional。
Optional<Integer> optional1 = Optional.ofNullable(1); Optional<Integer> optional2 = Optional.ofNullable(null); Optional<Integer> filter1 = optional1.filter((a) -> a == null); Optional<Integer> filter2 = optional1.filter((a) -> a == 1); Optional<Integer> filter3 = optional2.filter((a) -> a == null); System.out.println(filter1.isPresent());// false System.out.println(filter2.isPresent());// true System.out.println(filter2.get().intValue() == 1);// true System.out.println(filter3.isPresent());// false
get():从Optional实例中取回实际值对象,实例不存在抛出NPE
String name="John"; Optional<String> opt=Optional.ofNullable(name); assertEquals("John",opt.get());
map():返回一个Optional对象,它包含的是函数式接口的返回值,如果返回值为null则这个Optional就是一个空Optional对象
源码
应用
User user=new User("anna@gmaiil.com","1234"); String email=Optional.ofNullable(user); .map(u -> u.getEmail()) .orElse("default@gmail.com"); assertEquals(email,user.getEmail());
flatMap():用法上和map()相同,但参数要求必须是Optional对象
Optional<String> username=Optional.ofNullable(getUserById()) .flatMap(user -> Optional.of(user.getUsername())) .flatMap(name -> Optional.of(name.toLowerCase()));
用法
假设有一个Person类,含有Address属性,Address属性包含code字段
//Person类 public class Person { private Address address; public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } //Address类 public class Address { private String code; public String getCode() { return code; } public void setCode(String code) { this.code = code; } } //检查这些属性是否是valid的,可以看到,篇幅很长 private boolean validAddress(Person person){ if(person!=null){ //第一层判断 if(person.getAddress()!=null){ //第二层 String code=person.getAddress().getCode(); return code!=null; //第三层 }else{ return false; } }else{ return false; } }
但如果预先就将这些属性设置为Optional(或者在判断时构造为Optional),那么看起来会稍微舒服一点
//Person类 public class Person { private Optional<Address> address; public Optional<Address> getAddress() { return address; } public void setAddress(Optional<Address> address) { this.address = address; } } //Address类 public class Address { private Optional<String> code; public Optional<String> getCode() { return code; } public void setCode(Optional<String> code) { this.code = code; } } //判断 private boolean validAddress2(Person person2){ Optional<Person> person=Optional.ofNullable(person2); return person.flatMap(Person::getAddress) .flatMap(Address::getCode) .filter(x -> x.length()>6) .isPresent(); }
- 代码实例:SpringMvc02/Test1、Person、Address