美文网首页
Optional容器类

Optional容器类

作者: 不知名的蛋挞 | 来源:发表于2018-07-31 10:02 被阅读8次

    Optional<T>类是一个容器类,代表一个值存在或不存在,原来用null表示一个值不存在,现在Optional可以更好地表达这个概念。并且可以避免空指针异常。

    • Optional.of(T t):创建一个Optional实例。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException
    private final T value;
    private Optional(T value) {
            this.value = Objects.requireNonNull(value);
    }
    
    public static <T> Optional<T> of(T value) {
            return new Optional<>(value);
        }
    
    • Optional.empty():创建一个空的Optional实例。即该 Optional 中不包含值。
    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;
    }
    
    • Optional.ofNullable(T t):若 t 不为null,创建Optional实例,否则创建空实例。该方法和 of 方法的区别在于,传入的参数可以为 null。因为该方法会判断传入的参数是否为 null,如果为 null 的话,返回的就是 Optional.empty()。
    public static <T> Optional<T> ofNullable(T value) {
            return value == null ? empty() : of(value);
    }
    
    • get():获取 Optional 包含的值,如果值不存在,如在一个Optional.empty 上调用 get() 方法的话,将会抛出 NoSuchElementException 异常。
    public T get() {
            if (value == null) {
                throw new NoSuchElementException("No value present");
            }
            return value;
        }
    
    • isPresent():判断是否包含值。
    • orElse(T t):如果调用对象包含值,返回该值,否则返回 t 。
    • orElseGet(Supplier s):当 Optional 中有值的时候,返回值;当 Optional 中没有值的时候,返回从该 Supplier 获得的值。
    • map(Function mapper):如果有值对其处理,然后将返回的值包装在 Optional 中返回,否则返回Optional.empty()。
    • flatMap(Function mapper):与map类似,区别在于,map 方法参数中的函数 mapper 输出的是值,然后 map 方法会使用 Optional.ofNullable 将其包装为 Optional;而 flatMap 要求参数中的函数 mapper 输出的就是 Optional。
    • filter(Predicate p):filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。

    【代码示例】

    public class TestOptional {
    
        @Test
        public void test1(){
            Optional<Employee> op = Optional.of(new Employee());
            Employee e = op.get();
            System.out.print(e);
        }
    
        @Test
        public void test2(){
            // 第一行(也就是op.get()之前)就会会产生NullPointException异常,能快速锁定传入的就是空值
            Optional<Employee> op = Optional.of(null);
            System.out.print(op.get());
    
            // 构建一个空的Optional,不会产生异常
            Optional<Employee> op1 = Optional.empty();
            System.out.print(op1.get());
    
            Optional<Employee> op2 = Optional.ofNullable(new Employee());
            System.out.print(op2.get());
    
            // op3.get() 会产生NullPointException异常
            Optional<Employee> op3 = Optional.ofNullable(null);
            System.out.print(op3.get());
        }
    
        @Test
        public void test3(){
            Optional<Employee> op = Optional.ofNullable(null);
    
            // 判断是否包含值,如果包含则打印
            /*if(op.isPresent()){
                System.out.print(op.get());
            }*/
    
            // 如果op.get()是空那么就返回默认值,这样就不会产生空指针异常
            Employee emp = op.orElse(new Employee("张三",18,888.9, Employee.Status.FREE));
            System.out.print(emp);
        }
    
        @Test
        public void test4(){
            Optional<Employee> op = Optional.ofNullable(null);
    
            // 函数式接口,可以写任何你想要的功能,而不仅仅是new Employee()
            Employee emp = op.orElseGet(()->new Employee());
            System.out.print(emp);
        }
    
        @Test
        public void test5(){
            Optional<Employee> op = Optional.ofNullable(new Employee("张三",18,888.9, Employee.Status.FREE));
            Optional<String> str = op.map((e)->e.getName());
            System.out.print(str.get());  //输出“张三”
        }
    
        @Test
        public void test6(){
            Optional<Employee> op = Optional.ofNullable(new Employee("张三",18,888.9, Employee.Status.FREE));
            // flapMap要求返回值为 Optional<U>,进一步避免空指针的影响
            Optional<String> str = op.flatMap((e) -> Optional.of(e.getName()));
            System.out.print(str.get());  //输出“张三”
        }
    }
    

    Optional的好处

    public class Godness {
    
        // 女神一定有名字,这样的值就可以不用封装到Optional中
        private String name;
    
        public Godness(String name) {
            this.name = name;
        }
    
        public Godness() { }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    public class Man {
    
        private Godness godness;
    
        public Man() { }
    
        public Man(Godness godness) {
            this.godness = godness;
        }
    
        public Godness getGodness() {
            return godness;
        }
    
        public void setGodness(Godness godness) {
            this.godness = godness;
        }
    }
    
    public class NewMan {
    
        /**
         * 每个男人心中有可能有女神,有可能没有。Optional<>就是封装有可能有有可能没有的值
         *
         * 如果不给Optional对象赋值,那么默认这个Optional对象就是null,就没有意义了,
         * 所以给Optional对象赋值为Optional.empty(),也就是一个空的Optional对象,而不是null
         */
        private Optional<Godness> godness = Optional.empty();
    
        public NewMan() {
        }
    
        public NewMan(Optional<Godness> godness) {
            this.godness = godness;
        }
    
        public Optional<Godness> getGodness() {
            return godness;
        }
    
        public void setGodness(Optional<Godness> godness) {
            this.godness = godness;
        }
    }
    
    public class TestMan {
    
        @Test
        public void test1(){
            //产生空指针异常,这个男人没有女神
            Man man = new Man();
            String name = getGodnessName(man);
            System.out.print(name);
    
            Optional<NewMan> op = Optional.ofNullable(null);
            String str = getGodnessName2(op);  //不能直接传null,会产生NullPointException
            System.out.print(str);
        }
    
        // 需求:获取一个男人心中女神的名字
        public String getGodnessName(Man man){
            if(man!=null){
                Godness gn = man.getGodness();
                if(gn!=null){
                    return gn.getName();
                }
            }
            return "石原里美";
        }
    
        //传入参数也可能是空值,所以我们也可以用Optional进行封装
        public String getGodnessName2(Optional<NewMan> man){
            return man.orElse(new NewMan())  // 输入参数为空则new 一个男人
                    .getGodness()
                    .orElse(new Godness("石原里美"))   //没有女神就返回一个默认的女神
                    .getName();
        }
    }
    

    相关文章

      网友评论

          本文标题:Optional容器类

          本文链接:https://www.haomeiwen.com/subject/bjsxvftx.html