JDK1.8 Optional规范与基本使用

基本要义

阿里巴巴Java开发手册关于异常处理的规范:

【推荐】防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:

1)返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。

反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。 参考Java条件运算符的陷阱:自动拆箱与NPE - 知乎 (zhihu.com)

2) 数据库的查询结果可能为 null。

3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。

4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
场景:@Resource注入各种涉及到hsf远程调用的helper类时,需要对结果进行空指针判断。

5) 对于 Session 中获取的数据,建议 NPE 检查,避免空指针。

6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。

正例:使用 JDK8 的 Optional 类来防止 NPE 问题。

基本使用

import org.junit.Test;

import java.util.Optional;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/6/5
 */
public class OptionalTest {
    /**
     * 问题引入1
     */
    @Test
    public void problem1(){
        String name=null;
        System.out.println(name.length()); // NPE
    }

    /**
     * 问题引入2
     */
    @Test
    public void problem2(){
        System.out.println(problem2_1()); // 自动拆箱NPE
    }

    public int problem2_1(){
        Integer a=null;
        return a; // 会调用a.intValue()
    }

    /**
     * 以前需要进行非空判断
     */
    @Test
    public void test1(){
        String name=null;
        if(name!=null){
            System.out.println("字符串长度为:"+name.length());
        } else{
            System.out.println("字符串长度为空");
        }
    }

    // Optional是一个可以为null的容器对象,它的作用就是避免Null检查,防止NullPointerException

    /**
     * Optional创建方式
     */
    @Test
    public void test2(){
        // 第一种方式 of方法,of不支持null
        Optional<String> op1 = Optional.of("zhangsan");
//        Optional<Object> op2 = Optional.of(null);

        // 第二种方式 ofNullable方法,支持null
        Optional<String> op3 = Optional.ofNullable("zhangsan");
        Optional<Object> op4 = Optional.ofNullable(null);

        // 第三种方式 通过Empty()直接创建一个空对象null
        Optional<String> op5 = Optional.empty();
    }

    /**
     * Optional常见方法
     * get():如果Optional有值则返回,否则抛出NoSuchElementException异常
     * isPresent(): 判断Optional是否有value,有则返回true,否则返回false
     * T orElse(T t):如果Optional<T>包含value,则返回该value,否则返回t,其中value需要为类型T,也可以为null
     * orElseGet(Supplier<? extends T> other): 如果Optional包含值,则返回该value,否则返回Supplier<? extends T> other的返回值,其中supplier输入void返回<T>
     */
    @Test
    public void test3(){
        Optional<String> op1 = Optional.of("zhangsan");
        Optional<String> op2 = Optional.empty();
//        String s1 = op1.get();
//        System.out.println("用户名称为:"+s1);

//        System.out.println(op2.get()); // 空对象

        if(op1.isPresent()){
            System.out.println("用户名称为:"+op1.get()); // 用户名称为:zhangsan
        }else{
            System.out.println("s1是一个空对象");
        }

        if(op2.isPresent()){
            System.out.println("用户名称为:"+op2.get());
        }else{
            System.out.println("s2是一个空对象"); // s2是一个空对象
        }

        String s3 = op1.orElse(null);
        System.out.println(s3); // zhangsan

        String s4 = op2.orElse("王五");
        System.out.println(s4); // 王五

        String s5 = op2.orElseGet(()->{return "666";});
        System.out.println(s5); // 666
    }

    /**
     * ifPresent(Consumer<? super T> consumer): 如果存在值就做Consumer<? super T> consumer的动作,其中consumer输入<T>返回void
     */
    @Test
    public void test4(){
        Optional<String> op1 = Optional.of("zhangsan");
        Optional<String> op2 = Optional.empty();
        op1.ifPresent(s-> System.out.println("有值:"+s)); //有值:zhangsan
        op1.ifPresent(System.out::println); //zhangsan
    }


    /** 将偶数值进行过滤
     * op.filter(Predicate<? super T> predicate):对Optional<T>操作,根据predicate条件输出Optional<U>,其中Predicate<? super T> predicate输入<T>,输出boolean
     *
     * public Optional<T> filter(Predicate<? super T> predicate) {
     *         Objects.requireNonNull(predicate);
     *         if (!isPresent())
     *             return this;
     *         else
     *             return predicate.test(value) ? this : empty();
     *     }
     */
    @Test
    public void test5(){
        Optional<Integer> op = Optional.ofNullable(2222);
        Optional<Integer> ans=op.filter(s->s%2==0);
        System.out.println(ans); // 是偶数,过滤成功,输出Optional[2222]

        Optional<Integer> op2 = Optional.ofNullable(2223);
        Optional<Integer> ans2=op2.filter(s->s%2==0);
        System.out.println(ans2); // 是奇数,过滤失败,输出Optional.empty
    }


    /**
     * 将Person对象的name改为大写并打印出名字,通过Optional方式实现
     * op.map(Function<? super T, ? extends U> mapper):对Optional<T>操作,输出Optional<U> ,其中Function<? super T, ? extends U> mapper输入<T>,输出<U>
     *
     * map判断了value是否为null,如果为null返回empty(),否则返回mapper处理完后的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));
     *         }
     *     }
     */
    @Test
    public void test6(){
        Person person = new Person("zhangsan");
        Optional<Person> op = Optional.ofNullable(person);
        String name=getNameOptional(op);
        System.out.println(name); // ZHANGSAN
        System.out.println(person.getName()); // zhangsan,注意并未修改原来Person的属性,getNameOptional中是对新生成的Optional<String>的操作

        Person person2 = new Person(null);
        Optional<Person> op2 = Optional.ofNullable(person2);
        String name2 = getNameOptional(op2);
        System.out.println(name2); //空值
    }

    public String getNameOptional(Optional<Person> op){
        String msg=op.map(p->p.getName()) // Optional<String>或者Empty()
                .map(p->p.toUpperCase()) // Optional<String>或者Empty()
                .orElse("空值");
        return msg;
    }

    class Person{
        private String name;
        public Person(String name){
            this.name=name;
        }
        public String getName(){
            return this.name;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网民工蒋大钊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值