Java8 Optional类的API理解及使用
程序员文章站
2022-06-07 12:52:35
...
话说Optional类是为了避免空指针而生的,那怎么个避免法呢?以我个人的理解,其实也就是它内部帮我们判断一下然后需要我们提供一个实例而已。
典型的案例:
//1、创建一个空的Optional,stu对象肯定是不存在Student实例的
Optional<Student> stu = Optional.empty();
//2、因为stu是空的,orElse()方法就接收一个Student实例,那Optional可不就包含了一个Student实例了嘛,所以就不会抛出空指针异常咯
System.out.println(" 2.7.1 orElse():"+ stu.orElse(new Student(1, "11", 23,"stu不存在", 90))); //stu不存在,输出了else中实例化的Student对象
import java.util.Optional;
import java.util.function.Consumer;
public class OptionalDemo {
public static void main(String[] args) {
/**
* 使用Optional类应避免以下几种用法
* 1、调用 isPresent() --因为这跟使用if(obj != null)没有区别
* 2、调用 get()方法 --没有先调isPresent(),依然会抛出异常
* 3、Optional 类型作为类/实例属性 --IDEA工具都不建议使用而告警
* 4、Optional 类型作为方法参数 --方法中用到参数时,依然需要判断
*/
/**
* 三种方式创建Optional类实例
*/
//1.1、创建Optional类 Optional.empty();
Optional<Student> stu = Optional.empty();
//1.2、创建Optional类 Optional.of(obj); obj 不能是 null 值的
Optional<Student> stu1 = Optional.of(new Student(7, "李四", 23,"语文", 90));
/*
* 1.3创建Optional类 Optional.ofNullable(obj);
* Optional.ofNullable(obj): 接收null值,
* 传 null 进到就得到 Optional.empty(), 非 null 就调用 Optional.of(obj).
*/
Student s = null;
Optional<Student> stu2 = Optional.ofNullable(s);
/**
* 用法
*/
//2.1 get() --返回对象,如果对象不存在,直接抛出异常;不建议直接调用!!!如果要用,一定要先调用 isPresent()判断对象是否存在
//System.out.println(" Optional.get():"+ stu.get()); //这行会直接抛出异常 No value present,原因请看源码
//2.2 isPresent() --判断对象是否存在,如果对象不存在,返回false
System.out.println("2.2 Optional.isPresent():"+ stu.isPresent());
//2.3 ifPresent(Consumer<? super T> consumer) --对象存在,则可以通过函数做点什么业务,打印呀、改变下对象属性什么的
System.out.println("2.3 Optional.ifPresent(Consumer<? super T> consumer):" );
//2.3.1 打印一下
stu1.ifPresent(System.out::println); //打印一下
//2.3.2 改变一下属性(匿名类方式)
stu1.ifPresent(new Consumer<Student>() {
@Override
public void accept(Student t) {
t.setName("修改了名字");
}
}); //使用原始的匿名类方式
System.out.println("2.3.2 Optional.ifPresent 修改了名字:" + stu1.get());
//2.3.3 改变一下属性(lambda表达式)
stu1.ifPresent(student -> student.setName("修改了名字2")); // 使用lambda表达式
System.out.println("2.3.3 Optional.ifPresent 修改了名字(使用lambda表达式):" + stu1.get());
//2.4 filter 过滤,接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。
//new Student(7, "李四", 23,"语文", 90)
Optional<Student> filter = stu1.filter(student -> student.getAge()>25); //大于25岁,不通过,所以这里其实返回了Optional.empty
System.out.println("2.4 filter:" + filter.orElse(new Student())); //执行了else
//2.5 map 转换 接收一个Function<? super T, ? extends U>函数,并将Optional<T>转成Optional<U>
//new Student(7, "李四", 23,"语文", 90)
Optional<String> map = stu1.map(student -> student.getName()); //取出了Name属性值,并得到以name值初始化的Optional<String>对象
System.out.println("2.5 map:" + map.orElse("空值")); //输出 “修改了名字2” 因为2.3.3修改了它的属性
//2.6 flatMap 转换 接收一个Function<? super T, Optional<U>>函数,并将Optional<T>转成Optional<U>
//flatMap与map不同点在于接收参数的第二个参数,map是U,flatMap是Optional<U>
//new Student(7, "李四", 23,"语文", 90)
Optional<String> flatMap = stu1.flatMap(student -> Optional.ofNullable(student.getName())); //取出了Name属性值,并得到以name值初始化的Optional<String>对象
System.out.println("2.6 map:" + flatMap.orElse("空值")); //输出 “修改了名字2” 因为2.3.3修改了它的属性
//2.7 orElse() --存在则返回,否则返回传入的对象
System.out.println(" 2.7.1 orElse():"+ stu.orElse(new Student(1, "11", 23,"stu不存在", 90))); //stu不存在,输出了else
System.out.println(" 2.7.2 orElse():"+ stu1.orElse(new Student(1, "11", 23,"stu1存在", 90))); //stu1存在,输出stu1
System.out.println(" 2.7.3 orElse():"+ stu2.orElse(new Student(2, "22", 23,"stu2不存在", 90))); //stu2不存在,输出了else
//2.8 orElseGet(Supplier<? extends T> other) --存在则返回,否则由入参函数返回
//System.out.println(" Optional.orElseGet(Supplier):"+ stu.orElseGet(() -> getStu())); // 普通lambda表达式:入参是Supplier类型,没有输入,输出一个Student对象
System.out.println("2.8 orElseGet(Supplier):"+ stu.orElseGet(OptionalDemo:: getStu)); //这里用了方法引用 ClassName::staticMethod,调用了另一个方法实例化了一个Student对象
//2.9 orElseThrow(Supplier<? extends X>) --不存在则抛出一个异常
try {
System.out.println("2.8 orElseGet(Supplier):"+ stu.orElseThrow(Exception::new)); //因为stu不存在,所以这里抛出了一个异常
} catch (Exception e) {
System.out.println("2.9 orElseThrow: 因为stu不存在,所以这里抛出了一个异常");
}
}
/**
* 返回一个Student对象
* @return
*/
public static Student getStu(){
return new Student(3, "33", 23,"数学", 90);
}
private static class Student{
private int id; //id
private String name; //姓名
private int age; //年龄
private String subject; //学科
private float score; //分数
public Student(){}
public Student(int id,String name,int age,String subject,float score){
this.id=id;
this.name=name;
this.age=age;
this.subject=subject;
this.score=score;
}
@SuppressWarnings("unused")
public int getId() {
return id;
}
@SuppressWarnings("unused")
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@SuppressWarnings("unused")
public void setAge(int age) {
this.age = age;
}
@SuppressWarnings("unused")
public float getScore() {
return score;
}
@SuppressWarnings("unused")
public void setScore(float score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", subject=" + subject + ", score=" + score + "]";
}
@SuppressWarnings("unused")
public String getSubject() {
return subject;
}
@SuppressWarnings("unused")
public void setSubject(String subject) {
this.subject = subject;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((subject == null) ? 0 : subject.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (subject == null) {
if (other.subject != null)
return false;
} else if (!subject.equals(other.subject))
return false;
return true;
}
}
}
推荐阅读
-
使用java8中的Optional API解决nullPointException问题
-
Java日期时间API系列11-----Jdk8中java.time包中的新的日期时间API类,使用java8日期时间API重写农历LunarDate
-
Java8 Optional的使用及方法介绍
-
深入理解Java8新特性之Optional容器类的应用
-
Java8新特性——Optional类的判空使用
-
Java8新特性之Optional类的使用
-
Java8 Optional类的API理解及使用
-
实例理解Java8新特性中Stream API和Optional类的使用
-
JAVA 中的Optional类理解、学习与使用
-
Java日期时间API系列11-----Jdk8中java.time包中的新的日期时间API类,使用java8日期时间API重写农历LunarDate