详解Java8 Optional类{最全}
1:Optional
1.1 概述
Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException),提供了一些的方法代替过去的if-else处理逻辑,并与Stream流结合提供一致性的函数式编程.
注意: Optional 不支持Java本身提供的序列化与反序列化机制,也就是RPC不能使用Java提供的序列化机制
1.2 方法概览
序号 |
方法 |
方法说明 | |||
1 |
private Optional() |
无参构造,构造一个空Optional | |||
2 |
private Optional(T value) |
根据传入的非空value构建Optional | |||
3 |
public static<T> Optional<T> empty() |
返回一个空的Optional,该实例的value为空 | |||
4 |
public static <T> Optional<T> of(T value) |
根据传入的非空value构建Optional,与Optional(T value)方法作用相同 | |||
5 |
public static <T> Optional<T> ofNullable(T value) |
与of(T value)方法不同的是,ofNullable(T value)允许你传入一个空的value, 当传入的是空值时其创建一个空Optional,当传入的value非空时,与of()作用相同 |
|||
6 |
public T get() |
返回Optional的值,如果容器为空,则抛出NoSuchElementException异常 | |||
7 |
public boolean isPresent() |
判断当家Optional是否已设置了值 | |||
8 |
public void ifPresent(Consumer<? super T> consumer) |
判断当家Optional是否已设置了值,如果有值,则调用Consumer函数式接口进行处理 | |||
9 |
public Optional<T> filter(Predicate<? super T> predicate) |
如果设置了值,且满足Predicate的判断条件,则返回该Optional,否则返回一个空的Optional | |||
10 |
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) |
如果Optional设置了value,则调用Function对值进行处理,并返回包含处理后值的Optional,否则返回空Optional |
|||
11 |
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) |
与map()方法类型,不同的是它的mapper结果已经是一个Optional,不需要再对结果进行包装 | |||
12 |
public T orElse(T other) |
如果Optional值不为空,则返回该值,否则返回other | |||
13 |
public T orElseGet(Supplier<? extends T> other) |
如果Optional值不为空,则返回该值,否则根据other另外生成一个 | |||
14 |
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) |
如果Optional值不为空,则返回该值,否则通过supplier抛出一个异常 | |||
15 | public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) | 如果Optional值不为空,则返回该值,否则通过Optional.重新构造一个值 | |||
16 | public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) | 判断当家Optional是否已设置了值,如果有值,则调用Runable函数式接口进行处理 | |||
17 | public Stream<T> stream() | 将当前Optional 转换为诶Stream,如果值不存在则转换为empty stream ,存在则转换为包含值的流 |
2: 常用方法
2.1 构造方法
- 需要提前检查NPE 使用of方法
- 不管情况直接构造 使用ofNULLable*()方法
- empty() 方法 前面方法间接使用了这个方法
@Test(expected = NoSuchElementException.class) public void whenCreateEmptyOptional_thenNull() { Optional<User> emptyOpt = Optional.empty(); emptyOpt.get();// 没有值 将会抛出异常 } @Test(expected = NullPointerException.class) public void test_of() { User user=null; Optional<User> optional = Optional.of(user); } @Test public void test_ofNuLLAble() { User user=null; Optional<User> optional = Optional.ofNullable(user); optional.orElse(new User()); // 一般不使用 optional.get(); }
2.2 取得值
- get方法取不到值将会抛出异常NPE
- orElse系列方法,在null值的情况 将会提供默认值
// 取得值 @Test public void test_getValue() { Optional<String> opt = Optional.ofNullable(null); String str = opt.get(); String str2 = opt.orElse("Tom"); Assert.assertEquals("Tom", str2); String str3 = opt.orElseGet(()->"Tom2"); Assert.assertEquals("Tom2", str3); }
2.3 检查处理
// 检查处理 @Test public void test_Check() { Optional<String> opt = Optional.ofNullable(null); Assert.assertTrue(opt.isEmpty()); Assert.assertFalse(opt.isPresent());//not null if(opt.isPresent()) { String string = opt.get().toUpperCase(); } opt.ifPresent(x->x.toUpperCase()); //解决了if 问题 代码简洁 // 内部是runable 不能返回值 所以值这个方法功能有限 但是可以执行一些耗时操作 opt.ifPresentOrElse(x->x.toUpperCase(),()->System.out.println("sss")); }
2.4 返回值
@Test public void test_returnValue() { Optional<String> opt = Optional.ofNullable(null); Assert.assertEquals("Cat", opt.orElse("Cat")); Assert.assertEquals("Cat", opt.orElseGet(()->"Cat")); // or 为jdk9 新方法 String str_tom = opt.or(()->Optional.of("Tom")).get(); Assert.assertEquals("Tom", str_tom); }
2.5 返回异常
@Test(expected = NoSuchElementException.class) public void test_return_Exception() { Optional<String> opt = Optional.ofNullable(null); Assert.assertEquals("Cat", opt.orElseThrow()); Assert.assertEquals("Cat", opt.orElseThrow(()->new NoSuchElementException())); }
2.6 转换 与过滤
@Test public void test_MapAndFilter() { String [] str= new String[] {"a","b","c","d","1"}; Optional<String[]> opt = Optional.ofNullable(str); // filter String[] res = opt.filter(x->{ for (String s : x) { if(s.contains("e")) { return false; } } return true; }).get(); System.out.println(Arrays.toString(res)); // map 转大小 List<String> list=new ArrayList<>(); for(String x:str) {list.add(x);}; Optional<String> map = Optional.ofNullable(list).map(x->x.iterator().next().toUpperCase()); List<String> list2 = Optional.ofNullable(list).stream(). flatMap(x->x.stream().map(y->y.toUpperCase())).collect(Collectors.toList()); System.out.println(list2); }
2.7 链式操作
- 支持链式操作,序列化滞后
@Test public void Test_ChainCollec() { Street street = new Street("武汉轻工大学", 5); Address address = new Address(street); Person person = new Person("Tom", 12,address ); String string = Optional.ofNullable(person). flatMap(u->u.getAddress()) .flatMap(p->p.getStreet()) .map(l->l.getStreetName()) .orElse("default"); System.out.println(string); Address address2 = new Address(null); Person person2 = new Person("Tom", 12,null); String s3 = Optional.ofNullable(person2).flatMap(u->u.getAddress()) .orElse(new Address(null)) .getStreet() .orElse(new Street("武汉大学", 1)) .getStreetName(); System.out.println(s3); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream obr; try { obr = new ObjectOutputStream(bos); obr.writeObject(person); } catch (IOException e) { e.printStackTrace(); } ByteArrayInputStream inputStream = new ByteArrayInputStream(bos.toByteArray()); try { ObjectInputStream inputStream2 = new ObjectInputStream(inputStream); Person person23 = (Person) inputStream2.readObject(); System.out.println(person23.getAddress().get().getStreet().get().getStreetName()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
其他代码
class Person implements Serializable{ private String name; private Integer age; private Address address; public Person(String name, Integer age, Address address) { this.name = name; this.age = age; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Optional<Address> getAddress() { return Optional.ofNullable(this.address); } public void setAddress(Address address) { this.address = address; } } class Address implements Serializable{ private Street street ; public Optional<Street> getStreet() { return Optional.ofNullable(this.street); } public void setStreet(Street street) { this.street = street; } public Address(Street street) { super(); this.street = street; } } class Street implements Serializable{ private String streetName ; private Integer streetNo; public Street(String streetName, Integer streetNo) { this.streetName = streetName; this.streetNo = streetNo; } public String getStreetName() { return streetName; } public void setStreetName(String streetName) { this.streetName = streetName; } public Integer getStreetNo() { return streetNo; } public void setStreetNo(Integer streetNo) { this.streetNo = streetNo; } }
View Code