Optionals不是函数式接口,而是用于尽量避免空指针异常的漂亮工具.
api
Optional.of(T t) : 创建一个 Optional 实例,建议不要使用,如果of里面的参数为null,会报空指针,建议直接用Optional.ofNullable
Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
Optional.empty() : 创建一个空的 Optional 实例
ifPresent(T value),就是value值不为空时,做的一些操作。
isPresent(T value),判断是否包含值
get() 获取值,如果Optional为空就会抛异常
orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
代码案例
of
为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。
Optional<String> optional = Optional.of("xiaoming");
//传入null,抛出NullPointerException
Optional<Object> o = Optional.of(null);
ofNullable
为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
Optional<Object> o1 = Optional.ofNullable(null);
isPresent
值存在返回true,否则返回false
Optional<String> optiona2 = Optional.of("xiaoming");
System.out.println(optiona2.isPresent());
ifPresent
如果Optional有值则调用consumer处理,否则不处理
Optional<Object> o1 = Optional.ofNullable(null);
o1.ifPresent(s -> System.out.println(s));
Java8之前写法:
if(user!=null){
dosomething(user);
}
Java8写法:
Optional.ofNullable(user)
.ifPresent(u->{
dosomething(u);
});
get
Optional有值就返回,没有抛出NoSuchElementException
Optional<Object> o1 = Optional.ofNullable(null);
System.out.println(o1.get());
orElse
如果有值则将其返回,否则返回指定的其它值
Optional<Object> o1 = Optional.ofNullable(null);
System.out.println(o1.orElse("输出orElse")); // 输出orElse
orElseGet
orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值
Optional<Object> o1 = Optional.ofNullable(null);
System.out.println(o1.orElseGet(() -> "default value")); // default value
*注意:orElse 和 orElseGet 看似差不多,其实有很大不同;
当Optional 为空时,orElse和orElseGet 区别不大,但当Optional有值时,orElse仍然会去调用方法创建对象,而orElseGet不会再调用方法;在我们处理的业务数据量大的时候,这两者的性能就有很大的差异。
Java8之前写法
public User getUser(User user) throws Exception{
if(user!=null){
String name = user.getName();
if("zhangsan".equals(name)){
return user;
}
}else{
user = new User();
user.setName("zhangsan");
return user;
}
}
Java8之后的写法
public User getUser(User user) {
return Optional.ofNullable(user)
.filter(u->"zhangsan".equals(u.getName()))
.orElseGet(()-> {
User user1 = new User();
user1.setName("zhangsan");
return user1;
});
}
orElseThrow
如果有值则将其返回,否则抛出supplier接口创建的异常。
以前写法
public String getCity(User user) throws Exception{
if(user!=null){
if(user.getAddress()!=null){
Address address = user.getAddress();
if(address.getCity()!=null){
return address.getCity();
}
}
}
throw new Excpetion("取值错误");
}
用Java8写法
public String getCity(User user) throws Exception{
return Optional.ofNullable(user)
.map(u-> u.getAddress())
.map(a->a.getCity())
.orElseThrow(()->new Exception("取指错误"));
}
map
如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
Optional<String> optional = Optional.of("xiaoming");
String s = optional.map(e -> e.toUpperCase()).orElse("shiyilingfeng");
System.out.println(s); //输出: XIAOMING
flatMap
如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。与map不同的是,flatMap 的返回值必须是Optional,而map的返回值可以是任意的类型T
Optional<String> optional = Optional.of("xiaoming");
Optional<String> s = optional.flatMap(e -> Optional.of(e.toUpperCase()));
System.out.println(s.get()); //输出:XIAOMING
map和flatMa两种区别是返回值区别.
/**
* map和flatMa两种区别是返回值区别.
*/
@Test
public void ceui_测试map和flatMap() {
Optional<Employee> op = Optional.of(new Employee(101, "张三", 18, 9999.99));
//map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
Optional<String> op2 = op.map(Employee::getName);//获取姓名
System.out.println(op2.get());
//flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
Optional<String> op3 = op.flatMap(e -> Optional.of(e.getName()));//获取姓名
System.out.println(op3.get());
}
filter
filter(Predicate<? super T> predicate)
filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。
源码:
public final class Optional<T> {
//省略....
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
案例:
List<String> strings = Arrays.asList("rmb", "doller", "ou");
for (String s : strings) {
Optional<String> o = Optional.of(s).filter(s1 -> !s1.contains("o"));
System.out.println(o.orElse("没有不包含o的"));
}
//输出:
rmb
没有不包含o的
没有不包含o的
Optional<User> user1 = Optional
.ofNullable(user)
.filter(u -> u.getName().length()<6);
如上所示,如果 user 的 name 的长度是小于 6 的,则返回。如果是大于 6 的,则返回一个 EMPTY 对象。
是否会空指针的问题:
下面的 filter的案例2 会报空指针,其它的不会报空指针
@Test
public void filter的案例() {
Employee employee = null;
Employee rs = Optional.ofNullable(employee)
.filter(a -> a.getName().equals("张三"))
.orElse(null);
System.out.println("rs = " + rs); // 返回null, 并不会空指针
}
@Test
public void filter的案例2() {
Employee employee = new Employee();
Employee rs = Optional.ofNullable(employee)
.filter(a -> a.getName().equals("张三"))//这里空指针
.orElse(null);
System.out.println("rs = " + rs);
}
@Test
public void filter的案例3() {
Employee employee = new Employee();
Employee rs = Optional.ofNullable(employee)
.filter(a -> "张三".equals(a.getName()))
.orElse(null);
System.out.println("rs = " + rs); // 返回null, 并不会空指针
}
@Test
public void filter的案例4() {
Employee employee = new Employee();
employee.setName("张三");
Employee rs = Optional.ofNullable(employee)
.filter(a -> "张三".equals(a.getName()))
.orElse(null);
System.out.println("rs = " + rs); // 返回: Employee [id=0, name=张三, age=0, salary=0.0]
}
代码案例
//of():为非null的值创建一个Optional
Optional<String> optional = Optional.of("bam");
// isPresent(): 如果值存在返回true,否则返回false
optional.isPresent(); // true
//get():如果Optional有值则将其返回,否则抛出NoSuchElementException
optional.get(); // "bam"
//orElse():如果有值则将其返回,否则返回指定的其它值
optional.orElse("fallback"); // "bam"
//ifPresent():如果Optional实例有值则为其调用consumer,否则不做处理
optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b"
import e_Lambda表达式.entity.Employee;
import e_Lambda表达式.j_Optional.entity.Godness;
import e_Lambda表达式.j_Optional.entity.Man;
import org.junit.Test;
import java.util.Optional;
/*
* 一、Optional 容器类:用于尽量避免空指针异常
* Optional.of(T t) : 创建一个 Optional 实例
* Optional.empty() : 创建一个空的 Optional 实例
* Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
* isPresent() : 判断是否包含值
* orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
* orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
* map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
* flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
*/
public class TestOptional {
/**
* 两种区别是返回值区别.
*/
@Test
public void ceui_测试map和flatMap() {
Optional<Employee> op = Optional.of(new Employee(101, "张三", 18, 9999.99));
/*map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()*/
Optional<String> op2 = op.map(Employee::getName);//获取姓名
System.out.println(op2.get());
/*flatMap(Function mapper):与 map 类似,要求返回值必须是Optional*/
Optional<String> op3 = op.flatMap((e) -> Optional.of(e.getName()));//获取姓名
System.out.println(op3.get());
}
@Test
public void ceui_如果包含的对象有值就返回值_否则就返回自己默认的() {
Optional<Employee> op = Optional.ofNullable(new Employee("张三"));
/*如果包含的对象有值就返回值,否则就返回自己默认的*/
Employee emp2 = op.orElseGet(() -> new Employee());
System.out.println(emp2);
System.out.println("-------------");
Optional<Employee> op2 = Optional.ofNullable(null);
/*如果包含的对象有值就返回值,否则就返回自己默认的*/
Employee a = op2.orElseGet(() -> new Employee("我是默认值"));
System.out.println(a);
}
@Test
public void ceui_判断是否包含值() {
Optional<Employee> op = Optional.ofNullable(new Employee());
if (op.isPresent()) {//判断是否包含值
System.out.println("包含值");
System.out.println(op.get());
}
}
@Test
public void ceui_如果为null就设计默认值避免空指针() {
Optional<Employee> op = Optional.ofNullable(null);
Employee emp = op.orElse(new Employee("张三"));
System.out.println(emp);
}
@Test
public void ceui_没内容空指针异常() {
// Optional<Employee> op = Optional.ofNullable(null);
// System.out.println(op.get()); //没有内容依然是空指针异常
//
// Optional<Employee> op = Optional.empty();
// System.out.println(op.get()); //没有内容依然是空指针异常
}
/**
* 创建Optional实例
*/
@Test
public void ceui_Optional创建实例() {
Employee employee = new Employee();
System.out.println("employee = " + employee);
System.out.println("-------------");
Optional<Employee> op = Optional.of(new Employee());
Employee emp = op.get();
System.out.println(emp);//获取内容和创建是一样的.
Employee employee1 = null;
//也会出现空指针异常
Optional<Employee> employee11 = Optional.of(employee1);
}
@Test
public void test5() {
Man man = new Man();
String name = getGodnessName(man);
System.out.println(name);
}
//需求:获取一个男人心中女神的名字
public String getGodnessName(Man man) {
if (man != null) {
Godness g = man.getGod();
if (g != null) {
return g.getName();
}
}
return "张";
}
}