JDK1.8新特性总结 - 篇四(Optional容器类)

一. 简介         

         为了尽可能的避免空指针异常,jdk8中提出了Optional类。它是一个容器类,代表一个值是否实际存在。

         以下是Optional类的常用方法:

         1. public static<T>  Optional<T> of(T value)

         2. public static<T> Optional<T> empty();

         3. public static <T> Optional<T> ofNullable(T value)

         4. public boolean isPresent()

         5. public T orElse(T other)

         6. public T orElseGet(Supplier<? extends T> other)

         7. public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

         8. public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

         下面我们来逐一分析这些方法如何使用。

二. 应用

      1. public static<T>  Optional<T> of(T value)

             创建一个包含t类型对象的Optional实例,如果t为null,Optional.of(null)则会报错: NullPointerException。实际使用时可以这样用:

Optional<Employee> op1 = Optional.of(new Employee());
System.out.println(op1.get());

             源码:

public static <T> Optional<T> of(T value) {
	return new Optional<>(value);
}

             发现调用了Optional的构造函数。再往下看,

private Optional(T value) {
	this.value = Objects.requireNonNull(value);
}

            调用了Objects工具类(这种java.util包下类似的工具类常见的还有Collections,Arrays等)中的静态方法requireNonNull()

public static <T> T requireNonNull(T obj) {
	if (obj == null) //若传入的对象为null,则返回NullPointerException
		throw new NullPointerException();
	return obj;
}

           

      2. public static<T> Optional<T> empty();

               创建一个空的Optional实例,生成的结果不能直接使用get(),否则报错NoSuchElementException。实际使用时可以这样用:

Optional<Employee> op2 = Optional.empty();
op2.get(); //这句话会报错: NoSuchElementException

              源码:

private static final Optional<?> EMPTY = new Optional<>();

private Optional() {
    this.value = null;
}

public static<T> Optional<T> empty() {
	@SuppressWarnings("unchecked")
	Optional<T> t = (Optional<T>) EMPTY;
	return t;
}


public T get() {
	if (value == null) {
		throw new NoSuchElementException("No value present");
	}
	return value;
}

               通过调用无参构造函数,返回了一个value值为null的Optional实例,如果对这个实例调用get()方法,那么一定会走入if条件判断语句,抛出NoSuchElementException异常。其中,value就是用来装载外部传入对象的容器

      3. public static <T> Optional<T> ofNullable(T value)

               若value不为null,返回包含value的Optional实例,否则返回空实例实际使用时可以这样用:

Optional<Employee> op3 = Optional.ofNullable(
		new Employee("Jack", 25, 25000D, Status.BUSY)
);
System.out.println(op3.get());

                ofNullable()就是empty()和of()的组合,请看源码:

public static <T> Optional<T> ofNullable(T value) {
	return value == null ? empty() : of(value);
}

      4. public boolean isPresent()

               判断Optional实例中承载的对象是否是null。实际使用时可以这样用:

boolean flag = op3.isPresent(); //op3 是一个Optional<T>实例
System.out.println(flag);

               源码一目了然:

public boolean isPresent() {
	return value != null;  //若存在,则返回true,否则返回false
}

      5. public T orElse(T other)

                若调用方法的Optional实例承载的对象(value)不为null,则返回该对象,否则返回other。此方法一般用于补充前面的方法,避免NullPointerException的发生,起到保险的作用。实际使用时可以这样用:

               

//Optional<Employee> op3 = Optional.of(
//		new Employee("Jack", 25, 250000D, Status.BUSY)
//);

Optional<Employee> op3 = Optional.empty();

Employee employee = op3.orElse(
		new Employee("Blue", 26, 30000D, Status.VOCATION)
);

//若op3中的值存在,则返回op3本身的值,否则返回名称为"Blue"的对象
System.out.println(employee);

                 源码:

public T orElse(T other) {
	return value != null ? value : other;
}

      6. public T orElseGet(Supplier<? extends T> other)

               与orElse()非常类似,但有时候我们不方便直接返回一个对象,而是需要进行一系列的逻辑处理后才能返回对象,所以jdk8为我们提供了orElseGet(),入参是Supplier供给型接口(如果对Supplier陌生,请点击此链接)。实际使用时可以这样用:

op3.orElseGet(() -> {
	System.out.println("逻辑处理语句");
	Employee employee= new Employee("Kate", 24, 15000D, Status.RELAX);
	return employee;
});

               源码:

public T orElseGet(Supplier<? extends T> other) {
    //如果Optional本身承载的value对象不为null,那么直接返回该对象。
    //否则,返回自定义的供给型接口返回的对象!
	return value != null ? value : other.get();
}

      7. public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

                若调用方法的Optional实例承载的对象(value)不为null,则对这个对象进行加工,并返回处理后的Optional,否则返回Optional.Empty()。实际使用时可以这样用:

//返回Employee员工对象中的"员工名称"属性
Optional<String> op4 = op3.map(Employee::getName);

                源码: 

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    //Function不能为空
	Objects.requireNonNull(mapper);
    //value必须有值
	if (!isPresent())
		return empty(); //value为null,则返回空的Optional实例
	else {
        //之所以使用ofNullable(),因为被函数加工后的value也有可能为null
		return Optional.ofNullable(mapper.apply(value));
	}
}

      8. public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

          与map类似,只不过要求返回值必须是一个Optional实例。实际使用时可以这样用:

Optional<String> op5 = op3.flatMap(
		(e) -> Optional.of(e.getName())
);

         源码: 

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));
	}
}
发布了45 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/miaomiao19971215/article/details/90635035