创建Optional实例
Optional对象可能包含值也可能为空
@Test
public void test02(){
Optional<User> u = Optional.empty();
u.get();
}
使用上面那种方法创建Optional实例,如果使用get()方法访问u变量的值会报 NoSuchElementException。
我们也可以使用ofNullable()和of()方法来创建包含值的Optional实例,我们在明确对象不为Null的时候可以使用of()方法,但是不确定对象存不存在的时候就使用ofNullable()方法。
@Test
public void test03(){
User user = null;
//使用of(),如果user为null的话会报空指针错误
Optional<User> a = Optional.of(user);
//使用ofNullable()方法,把null作为参数传入的时候不会报空指针异常
Optional<User> b = Optional.ofNullable(user);
}
访问Optional对象的值
从Optional实例中取回实践对象的方法之一是使用get()方法
@Test
public void testOptional04(){
String name = "jin";
Optional<String> user = Optional.ofNullable(name);
assertEquals("jin", user.get());
}
在第一个例子里面,如果调用get()方法的对象为null还是会报空指针异常,因此我们要首先判断调用get()方法的对象是否存在。我们可以调用isPresent()方法判断Optional实例是否存在,如果存在则返回true。
但是一个对象存在也并不能代表它下面的属性都村在,如果某个属性没有赋值的话该属性的值也可能为null,只不过对象调用get()方法获取该属性的时候不会报空指针异常。
@Test
public void testOptional05(){
User user = new User(10,"jin");
Optional<User> u = Optional.ofNullable(user);
assertTrue(u.isPresent());
assertEquals(u.get().getName(),user.getName());
}
判断值是否存在还有另外一个方法ifPresent(),如果值存在则使用该值调用consumer,否则不做任何事情。
void ifPresent(Consumer<? super T> consumer)
如果值存在则使用该值调用 consumer , 否则不做任何事情。
opt.ifPresent( u -> assertEquals(user.getEmail(), u.getEmail()));
上面的程序只有当用户不为空的时候才会去运行lamda表达式
返回默认值
Optional类提供了API用以返回对象值,或者对象为空的时候返回默认值,这里的第一个方法是orElse()方法,这个方法的工作方式就是如果有值则返回值,没有值则返回传递给它的参数值
@Test
public void testOptional06(){
User user = new User(10,"jin");
User user1 = null;
//这里的user1为空所以返回了user对象,如果对象的初始值不为null的话orElse()方法里面的默认值就会被忽略
User result = Optional.ofNullable(user1).orElse(user);
assertEquals(result.getName(),"jin");
}
这里的user1为空所以返回了user对象,如果对象的初始值不为null的话orElse()方法里面的默认值就会被忽略。
第二种同类型的API是orElseGet(),这个方法会在有值的时候返回值,如果没有值它就会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果。
@Test
public void testOptional06(){
User user = new User(10,"jin");
User user1 = null;
//这里的user1为空所以返回了user对象,如果对象的初始值不为null的话orElse()方法里面的默认值就会被忽略
//User result = Optional.ofNullable(user1).orElse(user);
User result = Optional.ofNullable(user1).orElseGet( () -> user);
assertEquals(result.getName(),"jin");
}
上面的代码里面,user1为空就执行了orElseGet()方法里面的方法并将结果返回来。
orElse() 和 orElseGet() 的不同之处
当对象为空的时候,两种方法都需要执行CreateUser()方法,看不出有什么区别。
@Test
public void testOptional07(){
User user = new User(10,"jin");
User user1 = null;
//这里的user1为空所以返回了user对象,如果对象的初始值不为null的话orElse()方法里面的默认值就会被忽略
System.out.println("****orElse方法*****");
User result = Optional.ofNullable(user1).orElse(CreateUser());
System.out.println("****orElseGet方法****");
User result1 = Optional.ofNullable(user1).orElseGet(() -> CreateUser());
}
private User CreateUser(){
System.out.println("****CreateUser****");
return new User(10,"jin");
}
执行结果:
****orElse方法*****
****CreateUser****
****orElseGet方法****
****CreateUser****
当对象不为空时,orElse()方法依然会执行CreateUser()方法而orElseGet()方法则不会再执行CreateUser()方法了。
@Test
public void testOptional07(){
User user = new User(10,"jin");
User user1 = null;
//这里的user1为空所以返回了user对象,如果对象的初始值不为null的话orElse()方法里面的默认值就会被忽略
System.out.println("****orElse方法*****");
User result = Optional.ofNullable(user).orElse(CreateUser());
System.out.println("****orElseGet方法****");
User result1 = Optional.ofNullable(user).orElseGet(() -> CreateUser());
}
private User CreateUser(){
System.out.println("****CreateUser****");
return new User(10,"jin");
}
执行结果如下:
****orElse方法*****
****CreateUser****
****orElseGet方法****
在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。
还有一个方法是orElseThrow()方法,它会在对象为null的时候抛我们自己指定的异常,而不总是抛空指针异常
@Test
public void testOptional08(){
User user = new User(10,"jin");
User user1 = null;
User result1 = Optional.ofNullable(user1).orElseThrow(() -> new IllegalArgumentException());
}
转换值:有很多种方法可以转换Optional的值,如map() filter()方法等,这两个方法的使用和Stream流中对应的方法很相似
@Test
public void testOptional09(){
User user = new User(10,"jin");
String name = Optional.ofNullable(user).map(u -> u.getName()).filter(a -> a.contains("h")).orElse("haha");
System.out.println(name);
}
与Stream API相结合,可以有巨大威力。
@Test
public void testOptional10(){
// List<Employee> list = EmployeeData.getEmployees();
List<Employee> list = null;
Optional.ofNullable(list).orElse(Collections.emptyList())
.stream()
.map(e -> e.getAge())
.filter(s -> s > 30)
.forEach(System.out::println);
}