Optional 接口初使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37960603/article/details/85063671

Optional 接口

源码

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> {
 
    private static final Optional<?> EMPTY = new Optional<>();

    private final T value;

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

    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);
    }

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

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

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

    public boolean isPresent() {
        return value != null;
    }

    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }

    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));
        }
    }
    
    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));
        }
    }

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

    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }
    
    @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);
    }
    
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }
    
    @Override
    public String toString() {
        return value != null
            ? String.format("Optional[%s]", value)
            : "Optional.empty";
    }
}

有时候看看源码也是一种享受啊,学习源码的这种编码方式,让我受益匪浅。

接下来,说说 Optional 接口的方法:

构造方法

构造一个 value 属性为 null 的 Optional 实例

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

构造一个 value 属性不为 null 的 Optional 实例,如果传递过来的 value 参数为 null 会抛出 NullPointerException 异常。

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

Objects.requireNonNull() 源码:

public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
}

两个构造方法都是 private 等级的访问权限,所有我们不能直接使用 new 关键字创建 Optional 实例。

of() 方法

of() 方法内部调用有参构造方法创建一个 Optional 实例。
因为 of() 方法在内部调用了有参构造方法,所以当 value 参数为 null 时,of() 方法会抛出 NullPointerException 异常,所以说 of() 方法会创建一个 value 属性不为 null 的Optional 实例(创建成功的基础上)。

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

测试:

User.java:

package entity;

public class User {

    // 用户默认名字
    public static final String  DEFAULT_NAME = "Kaven";
    // 用户默认年龄
    public static final int DEFAULT_AGE = 20;
    // 用户的年龄
    private int age;
    // 用户的名字
    private String name;

    public User(){}

    public User(int age , String name){
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj == null) return false;
        else{
            if(obj instanceof User){
                User user = (User) obj;
                if(this.name.equals((user).name) && this.age == user.age) return true;
                else return false;
            }
            else return false;
        }
    }
}

testOptional.java:

package test;

import entity.User;

import java.util.Optional;

public class testOptional {

    public static void main(String[] args){

        Optional<User> optional = Optional.of(new User()); // 正常
        Optional<User> optional1 = Optional.of(null); // 抛出空指针异常
    }
}

empty() 方法

EMPTY 属性是一个 value 属性为 null 的 Optional 实例,为什么需要 EMPTY 属性呢?以我的理解,EMPTY 属性相当于代替了所有的 value 属性为 null 的 Optional 实例,如果每次创建一个 value 属性为 null 的 Optional 实例,都要调用 Optional 无参构造方法去申请内存创建一个 Optional 实例的话,还不如使用唯一一个 value 属性为 null 的 Optional 实例来代替,这样无论是在时间或者空间上来说都是划得来的,所以 EMPTY 是有价值的。

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

empty() 方法就是返回了 EMPTY 属性,所以无论调用多少次 empty() 方法,返回都是一样的,返回唯一一个 value 属性为 null 的 Optional 实例-EMPTY 属性。

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

测试:

Optional<User> optional = Optional.empty();
Optional<User> optional1 = Optional.empty();
System.out.println(optional == optional1);

输出:true

ofNullAble() 方法

看源码应该很容易理解,就是当传递过来的 value 参数为 null 时,调用 empty(),value 参数不为 null 时,调用 of() 方法。
也就是说可以创建任何形式的 Optional 实例,无论 value 属性是不是为 null,都可以创建成功。

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

测试:

Optional<User> optional = Optional.ofNullable(new User()); // 正常
Optional<User> optional1 = Optional.ofNullable(null); // 正常

get() 方法

就是返回 Optional 实例的 value 属性。

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

测试:

Optional<User> optional = Optional.of(new User(20 ,"Kaven"));
User user = optional.get();
System.out.println(user.getAge());
System.out.println(user.getName());

输出:

20
Kaven

isPresent() 方法

如果 Optional 实例的 value 属性为 null ,返回 false,否则返回 true。
所以就是用来判断 Optional 实例的 value 属性是否为 null 的。

public boolean isPresent() {
        return value != null;
}

ifPresent() 方法

参数是一个 Consumer 实例,在 Consumer 接口 、 Predicate 接口初使用 这篇博客中我说过 ,我认为 Consumer 接口的主要作用是用来修改传递过来的参数的。所以我认为 ifPresent() 方法主要是用来修改 Optional 实例的 value 属性的。

public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
}

测试:

Optional<User> optional = Optional.of(new User(20 ,"Kaven"));
Consumer<User> consumer = user -> {
      user.setAge(21);
};
optional.ifPresent(consumer);
User user = optional.get();
System.out.println(user.getAge());
System.out.println(user.getName());

输出:

21
Kaven

filter() 方法

从源码中可以看出来,filter() 方法的参数是一个 Predicate 实例,所以以我的理解,可以先从方法的函数名开始,filter - 过滤,如 web 开发的过滤器,是不是有点熟悉的感觉,所以我觉得 filter() 方法也是起到过滤的作用,如果不匹配 Predicate 实例的 test() 方法的 Optional 实例会返回 EMPTY,也就是调用 empty(),否则返回本身;当然如果这个 Optional 实例本身就是一个 EMPTY(value 为 null,或者说 isPresent() = false),也返回本身。

public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
}

测试:

Optional<User> optional = Optional.of(new User(20 ,"Kaven-1"));
Predicate<User> predicate1 = user -> {
    return user.getName().equalsIgnoreCase("Kaven");
};
Predicate<User> predicate2 = user -> {
    return user.getName().equalsIgnoreCase("Kaven-1");
};
Optional<User> optional1 = optional.filter(predicate1);
System.out.println(optional1);
Optional<User> optional2 = optional.filter(predicate2);
System.out.println(optional2.get().getName());

输出:

Optional.empty // 重写了 toString()
Kaven-1

map() 方法

map() 方法,方法名让我想起了 mybatis 的映射文件 Mapper.xml,其实这个方法的作用我觉得也是映射,把 Optional<T> 实例映射成 Optional<U> 实例。

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));
        }
}

测试:
Admin.java:

package entity;

public class Admin extends User{

    // 管理员数量
    private static int Admin_Number = 0;
    // 管理员 id,为了简单管理员 id  就为当前管理员数量值
    private int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public static int adminNumAdd(){
        return ++Admin_Number;
    }
}

我们通过 map() 方法,把 Optional<User> 实例映射成 Optional<Admin>

Function<User , Admin> function = user ->{
      Admin admin = new Admin();
      admin.setAge(user.getAge());
      admin.setName(user.getName());
      admin.setId(Admin.adminNumAdd());
      return admin;
};

User user = new User(20 , "Kaven");
Optional<User> optional = Optional.of(user);
Optional<Admin> optionalAdmin = optional.map(function);
Admin admin = optionalAdmin.get();
System.out.println(admin.getAge());
System.out.println(admin.getName());
System.out.println(admin.getId());

输出:

20
Kaven
1

flatMap() 方法

和 map() 方法没有什么差别,都是把 Optional<T> 实例映射成 Optional<U> 实例,只不过 flatMap() 方法是通过 Function 实例更加直接的映射成 Optional<U> ,而 map() 方法是先映射成 U 实例再调用 ofNullable() 方法创建 Optional<U> 实例,单词 flat 也有直接的意思。

    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));
        }
}

测试:
代码差不多

Function<User , Optional<Admin>> function = user ->{
     Admin admin = new Admin();
     admin.setAge(user.getAge());
     admin.setName(user.getName());
     admin.setId(Admin.adminNumAdd());
     Optional<Admin> optionalAdmin = Optional.of(admin);
     return optionalAdmin;
};

User user = new User(20 , "Kaven");
Optional<User> optional = Optional.of(user);
Optional<Admin> optionalAdmin = optional.flatMap(function);
Admin admin = optionalAdmin.get();
System.out.println(admin.getAge());
System.out.println(admin.getName());
System.out.println(admin.getId());

输出:

20
Kaven
1

orElse()

看源代码可以看出来,如果 Optional 实例的 value 属性为 null,就返回 other 参数,否则就返回该 Optional 实例的 value 属性。
在我看来,就是选择值的优先级问题,总是会优先选择当前这个 Optional 实例的 value 属性,只有当这个 Optional 实例的 value 属性为 null 时,才选择其他的值。

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

测试:

User user = new User(20 , "Kaven");
Optional<User> optional = Optional.ofNullable(null);
User user_test = optional.orElse(user);
System.out.println(user_test.getAge());
System.out.println(user_test.getName());

Optional<User> optional_test = Optional.ofNullable(new User(21 ,"Wang"));
user_test = optional_test.orElse(user);
System.out.println(user_test.getAge());
System.out.println(user_test.getName());

输出:

20
Kaven
21
Wang

orElseGet() 、orElseThrow()

orElseGet() 源码:

public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
}

orElseThrow() 源码:

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
}

看源码应该也很容易理解,和 orElse() 相对比理解就好了,我就不测试了。

equals()、hashCode()、toString()

重写 Object 类的方法,自己看看源码就行了,不是重点。

要是有说的不对的地方,请指正,万分感谢。

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/85063671