栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java8 Optional类用法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java8 Optional类用法

文章目录
  • API介绍
    • 第一组
      • Optional(T value)
      • empty()
      • of(T value)
      • ofNullable(T value)
    • 第二组
      • orElse(T other),orElseGet(Supplier other)
      • orElseThrow(Supplier exceptionSupplier)
    • map(Function mapper)和flatMap(Function> mapper)
    • isPresent()和ifPresent(Consumer consumer)
    • filter(Predicate predicate)
  • 案例
    • 例子1
    • 例子2
    • 例子3

Java8 提供了Optional类来优化判空写法。
Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。

API介绍 第一组

这四个函数之间具有相关性,因此放在一起;

Optional(T value)

Optional(T value),即构造函数,它是private权限的,不能由外部调用的。

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

其余三个函数是public权限,供我们所调用。

empty()

Optional类内部还维护一个value为null的对象,大概就是长下面这样的:

public final class Optional {
    //省略....
    private static final Optional EMPTY = new Optional<>();
    private Optional() {
        this.value = null;
    }
    //省略...
    public static Optional empty() {
        @SuppressWarnings("unchecked")
        Optional t = (Optional) EMPTY;
        return t;
    }
}

empty() 的作用就是返回EMPTY对象。

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

of(T value)函数内部调用了构造函数。根据构造函数的源码我们可以得出两个结论:

  • 通过of(T value)函数所构造出的Optional对象,当Value值为空时,依然会报NullPointerException。
  • 通过of(T value)函数所构造出的Optional对象,当Value值不为空时,能正常构造Optional对象。

使用场景:
当我们在运行过程中,不想隐藏NullPointerException。而是要立即报告,这种情况下就用Of函数。

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

相比较of(T value)的区别就是:
当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。

第二组

这三个函数放一组进行记忆,都是在构造函数传入的value值为null时,进行调用的。

orElse(T other),orElseGet(Supplier other)

详细API源码如下:

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


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

orElse和orElseGet的用法如下所示,相当于value值为null时,给予一个默认值:

public class OptionalTest {

    public static void main(String[] args) throws Exception {
        // Person person = null;
        Person person = new Person();
        Person person1 = Optional.ofNullable(person).orElse(creatPerson());
        System.out.println(person1);
        Person person2 = Optional.ofNullable(person).orElseGet(() -> creatPerson());
        System.out.println(person2);

        Optional.ofNullable(person).orElseThrow(() -> new Exception("没有此人"));
    }

    public static Person creatPerson() {
        Person person = new Person();
        person.setName("Tom");
        person.setAge(18);
        person.setNickName("cat");
        System.out.println("create person");

        return person;
    }
}

这两个函数的区别:

上面的测试可以发现。
当person值不为null时,orElse函数依然会执行creatPerson()方法,
而orElseGet函数并不会执行creatPerson()方法;

orElseThrow(Supplier exceptionSupplier)

orElseThrow,就是value值为null时,直接抛一个异常出去:

public  T orElseThrow(Supplier exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}
map(Function mapper)和flatMap(Function> mapper)

两个函数做的是转换值的操作:

public final class Optional {
    //省略....
     public Optional map(Function mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
    //省略...
     public Optional flatMap(Function> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }
}

这两个函数,在函数体上没什么区别。唯一区别的就是入参。
map函数所接受的入参类型为Function
而flapMap的入参类型为Function>。

示例1:

public class OptionalMapFilterDemo {
    public static void main(String[] args) {
        String password = "password";
        Optional  opt = Optional.ofNullable(password);

        Predicate len6 = pwd -> pwd.length() > 6;
        Predicate len10 = pwd -> pwd.length() < 10;
        Predicate eq = pwd -> pwd.equals("password");

        boolean result = opt.map(String::toLowerCase).filter(len6.and(len10 ).and(eq)).isPresent();
        System.out.println(result);
    }
}

示例2:

public class Person {

    private String name;
    private int age;
    private String nickName;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Optional getNickName() {
        return Optional.ofNullable(nickName);
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                ", nickName='" + nickName + ''' +
                '}';
    }
}
public static void testMap() {
    Person newPerson = creatPerson();
    Integer age = Optional.ofNullable(newPerson).map(e -> e.getAge()).get();
    System.out.println("newPerson age = " + age);
    
    String nickName = Optional.ofNullable(newPerson).flatMap(e -> e.getNickName()).get();
    System.out.println("newPerson nickName = " + nickName);
}
isPresent()和ifPresent(Consumer consumer)

这两个函数放在一起记忆,isPresent即判断value值是否为空,而ifPresent就是在value值不为空时,做一些操作。

filter(Predicate predicate)

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。

案例 例子1

比如,在主程序中

以前写法

if(user!=null){
    dosomething(user);
}

java8写法

 Optional.ofNullable(user)
    .ifPresent(u->{
        dosomething(u);
});
例子2

在函数方法中

以前写法

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("取指错误"));
}
例子3

以前写法

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

采用这种链式编程,虽然代码优雅了。但是,逻辑性没那么明显,可读性有所降低,大家项目中看情况酌情使用。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号