JDK8 中引入的 Optional 类可以解决空指针异常, 让我们省略繁琐 的非空判断. Optional 类就是一个可以为 null 容器, 或者保存指定类型的数据, 或者为 null.
package java.util;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public final class Optional<T> {
/**
* Common instance for {@code empty()}.
*/
private static final Optional<?> EMPTY = new Optional<>();
/**
* If non-null, the value; if null, indicates no value is present
*/
private final T value;
/**
* value为空的Optional类型对象
*/
private Optional() {
this.value = null;
}
/**
* 返回一个空的Optional对象
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
/**
* 如果为空,抛出一个空指针异常
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
* 封装为一个Optional 类型的对象
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
* 把指定的 value 值封装为 Optional 对象,如果
* value 为 null 返回一个空的 Optional 对象
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* 如果值存在返回, 如果不存在抛出异常 NoSuchElementException
*/
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
/**
* 判断值是否存在
*/
public boolean isPresent() {
return value != null;
}
/**
* 如果值存在就执 行 consumer 函数,否则什么也不做
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
/**
* 如果有值,返回符合 predicate 条件的 Optional 对象, 否则返回空的 Optional 对象
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
/**
* 如果值存在 就执行 mapper 映射函数,
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
/**
* 如果 有值,执行 mapper 映射函数,返回 Optional 对象, 如果没有值返 回空的 Optional 对象
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
/**
* 如果值存在就返回,如果不存在返回 other
*/
public T orElse(T other) {
return value != null ? value : other;
}
/**
* 如果存在就返回值, 如果不存在,执行 Supplier 返回另外一个值
*/
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
/**
* 如果存在就返回该值,如果不存在抛出由 exceptionSupplier 生成的异常
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
/**
* 重写equals方法
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Optional)) {
return false;
}
Optional<?> other = (Optional<?>) obj;
return Objects.equals(value, other.value);
}
/**
* Objects类的hashcode方法
*/
@Override
public int hashCode() {
return Objects.hashCode(value);
}
/**
* 重写toString 方法
*/
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
}
public class Test01 {
public static void main(String[] args) {
//1 把一个字符串封装为Optional对象
//参数不能为null,否则抛出NullPointException
Optional<String> ofString = Optional.of("hello");
//Optional ofString1 = Optional.of(null);
//2 为指定的值创建Optional对象(可以为空)
Optional<String> ofString2 = Optional.ofNullable(null);
System.out.println(ofString2);//Optional.empty
//3 直接创建一个空的Optional对象
Optional<Object> empty = Optional.empty();
System.out.println(empty);//Optional.empty
//4 获得 Optional 对象中的值,如果值不存在会产生异常
String text = ofString.get();
System.out.println(text);
String text2 = ofString2.get(); //java.util.NoSuchElementException
//5 如果 Optional 对象中有值就返回,没有则返回指定的其他值
text = ofString.orElse("another");
//6 如果有值就返回,如果 Optional 对象中没值则创建一个新的
text = ofString2.orElseGet(() -> "newString");
System.out.println( text ); //newString
//7 orElseThrow(),如果值存在就返回,否则抛出异常 /
text = ofString2.orElseThrow(NullPointerException::new);
text = ofString.orElseThrow(NullPointerException::new);
System.out.println( text );
//8 filter(),如果 Optional 对象有值返回满足指定条件的 Optional 对象
// , 否则返回空 的 Optional 对象
text = ofString.filter(s -> s.length() > 10).orElse("lenth is letter than 10");
System.out.println( text );
text = ofString.filter(s -> s.length() > 3).orElse("lenth is letter than 3");
System.out.println( text );
//9 如果 Optional 对象的值存在,执行 mapper 映射函数
text = ofString.map(x -> x.toUpperCase()).orElse("Failure");
System.out.println( text );
text = ofString2.map(x -> x.toUpperCase()).orElse("Failure");
System.out.println( text ); //Failure
//10 ifPresent() 如果 Optional 对象有值就执行 Consumer 函数
ofString.ifPresent(s -> System.out.println("处理数据" + s));
ofString2.ifPresent(s -> System.out.println("处理数据" + s)); //没有值什么也 不做 System.out.println("optional");
}
}
public class Test02 {
public static void main(String[] args) {
Address address = new Address("Beijing", "TianAnMen");
User user = new User("zhangsan", address);
User user1 = new User();
User user2 = null;
System.out.println(getName1(user));
System.out.println(getName2(user1));
System.out.println(getCity1(user2));
System.out.println(getCity2(user));
}
/**传统写法**/
//定义方法返回指定用户的用户名 ,如果用户名不存在返回unknown
public static String getName1(User user) {
if (user == null) { //判断参数接收的 User 对象是否为 null
return "unknown";
}
return user.name;
}
//Optional 可以解决空指针问题
public static String getName2(User user) {
return Optional.ofNullable(user) //把参数接收的 user 对象包装为 Optional 对象
.map(u -> u.name) //映射,只需要用户名
.orElse("unknown"); //存在就返回,不存在返回 unknown
}
/**传统写法**/
//定义方法返回指定用户的城市
public static String getCity1(User user) {
if (user != null) {
if (user.address != null) {
return user.address.city;
}
}
return "unkown";
}
//使用 Optional 返回用户的城市
public static String getCity2(User user) {
return Optional.ofNullable(user) //把参数对象包装为 Optional 对象
.map(u -> u.address) //映射用户的地址
.map(addr -> addr.city) //映射地址的城市
.orElse("Unkown"); //有就返回,没有返回 Unknown
}
}
//定义用户类
class User {
String name;
Address address;
public User(String name, Address address) {
this.name = name;
this.address = address;
}
public User() {
}
}
class Address {
String city;
String house;
public Address(String city, String house) {
this.city = city;
this.house = house;
}
}
如果每一个人都有一辆车,没辆车都有一个保险,每个保险都有一个名字,那么保险类、车类、人类就可以这样定义。
/**
* 保险类
*/
public class Insurance {
private String name;
public String getName() {
return name;
}
}
/**
* 汽车类
*/
public class Car {
//汽车有保险
private Insurance insurance;
public Insurance getInsurance() {
return insurance;
}
}
/**
* 人类
*/
public class Person {
//人有小汽车
private Car car;
public Car getCar() {
return car;
}
public Person setCar(Car car) {
this.car = car;
return this;
}
}
测试类:获取某一个人的小汽车的保险的名称
/**
* 每个人有一部车,每辆车都有保险,每个保险公司都有自己的名称
*/
public class Test {
public static void main(String[] args) {
Person lisi = new Person();
//lisi的car属性默认初始化为null
// getCarInsuranceName(lisi); //产生了空指针异常
Car benz = new Car(); //insurance默认初始化为null
lisi.setCar(benz);
getCarInsuranceName(lisi);
}
//获得某个人的汽车的保险的名称
public static String getCarInsuranceName3( Person person){
if ( person == null ){ //人不存在
return "Unknown";
}
Car car = person.getCar();
if (car == null){ //车不存在
return "Unknown";
}
Insurance insurance = car.getInsurance();;
if ( insurance == null){ //没有保险
return "Unknown";
}
return person.getCar().getInsurance().getName();
}
//获得某个人的汽车的保险的名称
public static String getCarInsuranceName2( Person person){
if ( person != null ){ //人存在
Car car = person.getCar();
if ( car != null ){ //人有车
Insurance insurance = car.getInsurance();
if ( insurance != null){ //车有保险
return insurance.getName();
}
}
}
return "Unknown";
}
//获得某个 人的汽车的保险的名称
public static String getCarInsuranceName( Person person){
return person.getCar().getInsurance().getName();
}
/*
这段代码存在问题:
并不是所有的人都有车, 如果没有车的话,getCar()会返回null,运行时会产生空指针异常
并不是所有的车都有保险,如果没有保险,getInsurance()返回null
*/
}
重新定义保险类、汽车类、人类
/**
* 保险类
*/
public class Insurance {
private String name;
public String getName() {
return name;
}
public Insurance setName(String name) {
this.name = name;
return this;
}
}
/**
* 汽车类
*/
public class Car {
//汽车品牌
private String brand;
//不能确定每辆汽车都有保险
private Optional<Insurance> insurance;
public Car(String brand, Optional<Insurance> insurance) {
this.brand = brand;
this.insurance = insurance;
}
public String getBrand() {
return brand;
}
public Car setBrand(String brand) {
this.brand = brand;
return this;
}
public Optional<Insurance> getInsurance() {
return insurance;
}
public Car setInsurance(Optional<Insurance> insurance) {
this.insurance = insurance;
return this;
}
}
/**
* 定义人类
*/
public class Person {
private String name;
//不确定是否有车
private Optional<Car> car;
public Person(String name, Optional<Car> car) {
this.name = name;
this.car = car;
}
public String getName() {
return name;
}
public Person setName(String name) {
this.name = name;
return this;
}
public Optional<Car> getCar() {
return car;
}
public Person setCar(Optional<Car> car) {
this.car = car;
return this;
}
}
测试类
/**
* 每个人可能有一部车,每辆车可能都有保险,每个保险公司都有自己的名称
*/
public class Test {
public static void main(String[] args) {
//1)创建保险对象
Insurance in1 = new Insurance();
in1.setName("pingan");
Optional<Insurance> insurance1 = Optional.ofNullable(in1); //有保险
Optional<Insurance> insurance2 = Optional.ofNullable(null); //保险为null
//2)创建小汽车对象
Car car1 = new Car("Geely", insurance1); //Geely汽车有保险
Car car2 = new Car("Haval", insurance2); //Haval汽车没有保险
Optional<Car> carOptional1 = Optional.ofNullable(car1); //车有保险
Optional<Car> carOptional2 = Optional.ofNullable(car2); //车无保险
Optional<Car> carOptional3 = Optional.ofNullable(null) ; //没有车
//3)创建Person对象
Person p1 = new Person("lisi", carOptional1); //lisi有车,有保险
Person p2 = new Person("wangwu", carOptional2); //wangwu,有车,没有保险
Person p3 = new Person("zhaoliu", carOptional3); //zhaoliu, 没有车
//4)使用Optional包装Person对象
Optional<Person> person1 = Optional.ofNullable(p1); //有车,有保险
Optional<Person> person2 = Optional.ofNullable(p2); //有车,没有保险
Optional<Person> person3 = Optional.ofNullable(p3); //没有车
//5)获得人的汽车品牌
System.out.println( person1.map(Person::getCar));
//返回一个Optional>类型的数据
System.out.println( person1.flatMap(Person::getCar));
//Optional
System.out.println( person1.flatMap(Person::getCar).map(Car::getBrand).orElse("Unknown"));
System.out.println( person2.flatMap(Person::getCar).map(Car::getBrand).orElse("Unknown"));
System.out.println( person3.flatMap(Person::getCar).map(Car::getBrand).orElse("Unknown"));
//6)获得人的汽车的保险的名称
System.out.println( person1.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknwon"));
System.out.println( person2.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknwon"));
System.out.println( person3.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknwon"));
}
}
注意:
1 .map() 和 flatMap() 方法的使用。map() 方法的返回值,又对结果进行了一次包装。具体可以看Optional类的源码
2. 明显可以看出使用Optional类型,作为成员变量的属性,可以减少很多非空判断,代码可读性更高。
3 在实际开发中应当多应用。