java 8新特性Optional类详解,超完整测试

代码中给了很详细的测试和注释,很容易看懂,建议仔细看一遍。控制台输出再最下方。
Optional是个容器,类型为Optional<YourClass>。
创建Optional可以用三种方法empty、of、ofNullable。
empty创建一个空的,of和ofNullable需要一个对象作为参数,放进Optional里面并返回,区别在于of里面不可以放进null,它会报错。可以通过ofNullable()可以接受空对象。

使用get提取出Optional里面的对象(为空时报错),用isPresent可以判断是否为空,返回值为boolean。

orElse不为空时返回自身,为空时返回设定的默认值,并用Optional包装。
例如:

int b=1;Optional\<int> a=Optional.of(b);
a.orElse(100)    //返回a自身

若a包含了非空的int,则返回这个包含了int的Optional;若为空,则返回一个包含了100的Optional。

filter可以过滤掉不符合要求或者为空的对象,同样的符合的时候返回自身,不符合的时候返回一个空的Optional。
例如:

 a.fliter(x->x==0)

若a里面不为空且存的对象的值为0(表达式返回true),返回a。否则返回空的Optional。

而map可以按你自己的爱好转换非空对象为其他任意类型对象,然后自动包装好并返回。
例如:

int b=100; Optional\<int> a=Optional.of(b);
a.map(x->String.valueOf(x));   //返回一个装着“100”的字符串的Optional

Optional强大之处在于很好地处理了null,不再需要一路判断null了。
如:
假设有一个对象a持有了b对象,b又持有了c,我们需要打印出c,如果不存在就打印默认值-1;
传统写法需要判断三次:a!=null, a.b!=null, a.b.c!=null
至少写三个if语句。
现在只需要把a装进Optional里,这里用A表示:

System.out.println(A.map(x->x.b).map(x->x.c).orElse(-1));

如果不希望有默认值:可以用

A.map(x->x.b).map(x->x.c).ifPresent(System.out::println);

实际上更常用的语句是:

MyClass b=new MyClass(10);
a.orElse(new MyClass(0)).get(); 

在java11里,建议用orElseThrow无参数版代替get

这里推荐先学习一下lambda表达式和Supplier、Consumer、Functional、Predicate四个函数式接口相关知识。
与上述函数对应关系分别为:
Consumer->ifPresent (注意是if不是is)
Functional->map
Predicate->fliter
Supplier->orElseGet

package com.crimson.master;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;

public class TestOptional
{

    public static void main(String[] args)
    {
        //test creation 测试三种创建方法,of()可能会报异常。这里test 13都是空的Optional,
        // 5因为异常没得到赋值,是null状态,是个空指针
        Optional<TestOptional>
                test1 = Optional.empty(),
                test2 = Optional.of(new TestOptional(2)),
                test3 = Optional.ofNullable(null),
                test4 = Optional.ofNullable(new TestOptional(4)),
                test5 = null;
        try
        {
            test5 = Optional.of(null);
        } catch (Exception e)
        {
            System.out.println("用of(null)创建test5时出现异常  " + e);
        }
        List<Optional<TestOptional>> list = Arrays.asList(test1, test3, test5);

        //test using 测试提取信息 使用get(),而isPresent判断是否为空
        System.out.println("开始提取信息");
        System.out.println("test2:" + test2.get() + " test4:" + test4.get());
        int count = -1;
        System.out.println("调用get时捕获到异常!");
        for (Optional<TestOptional> i : list)
        {
            try
            {
                count += 2;
                System.out.println(i.get());
            } catch (Exception e)
            {
                System.out.println("异常来自:test" + count + "异常为: " + e);
            }
        }
        System.out.println("测试isPresent");
        System.out.println("test1为:" + test1.isPresent() + " test2为:" + test2.isPresent());
        //test orElse orElseThrow orElseGet三种orElse方法
        // 三种方法仅当为空时才有效执行,不为空时返回原来的Optional
        System.out.println("测试orElse方法,依次测试123,or统一为100的值");
        System.out.println(test1.orElse(new TestOptional(100)));
        System.out.println(test2.orElse(new TestOptional(100)));
        System.out.println(test3.orElse(new TestOptional(100)));
        System.out.println("测试orElseGet,这里提供随机数");
        System.out.println(test3.orElseGet(() -> new TestOptional(new Random().nextInt())));
        try
        {
            System.out.println("测试orElseThrow抛出异常");
            System.out.println(test3.orElseThrow(
                    () -> {
                        return new Exception("test3正通过orElse抛出异常");
                    }));
        } catch (Exception e)
        {
            System.out.println(e);
        }

        //test fliter 测试过滤器,不为空且断言为true才返回原来的Optional,否则返回空的
        System.out.println("测试过滤器,测试124,判断是否a的值为1,等于返回自身,不等于返回空");
        System.out.println(test1.filter(x -> x.getA() == 1));
        System.out.println(test2.filter(x -> x.getA() == 1));
        System.out.println(test4.filter(x -> x.getA() == 1));

        //test ifPresent 如果不为空传给消费函数
        System.out.println("测试ifPresent,不为空时打印自身,为空时不操作,测试23");
        test2.ifPresent(x -> System.out.println(x));
        test3.ifPresent(x -> System.out.println(x));

        //测试映射方法 map 测试
        System.out.println("测试映射,不为空时映射,测试2,映射成100倍的int,装在Optional");
        System.out.println(test2.map(x -> x.getA() * 100).get());
    }

    private int a = 0;

    public String toString()
    {
        return String.valueOf(a);
    }

    TestOptional(int a)
    {
        this.a = a;
    }

    public int getA()
    {
        return a;
    }

    public void setA(int a)
    {
        this.a = a;
    }
}

这里是控制台的输出结果:

of(null)创建test5时出现异常  java.lang.NullPointerException
开始提取信息
test2:2 test4:4
调用get时捕获到异常!
异常来自:test1异常为: java.util.NoSuchElementException: No value present
异常来自:test3异常为: java.util.NoSuchElementException: No value present
异常来自:test5异常为: java.lang.NullPointerException
测试isPresent
test1为:false test2为:true
测试orElse方法,依次测试123,or统一为100的值
100
2
100
测试orElseGet,这里提供随机数
-1610499459
测试orElseThrow抛出异常
java.lang.Exception: test3正通过orElse抛出异常
测试过滤器,测试124,判断是否a的值为1,等于返回自身,不等于返回空
Optional.empty
Optional.empty
Optional.empty
测试ifPresent,不为空时打印自身,为空时不操作,测试23
2
测试映射,不为空时映射,测试2,映射成100倍的int,装在Optional
200

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值