说明

  • 老实话,Optional一直是我非常常用的一个类,使用函数式编程,将原本多行代码,缩略成一行,极大简洁了代码
  • 但在经常使用中,发现有时候原生的Optional并不能完全满足我的需求,在Hutool中找,发现确实有一个OptionalBean,但其已经被废弃了,因此才有了这个类
  • 通过对JDK16的学习,研究了Optional的新特性,并已经在开发中经常使用基于Optional复制后拓展的类
  • 讲老实话,经常使用Stream,有些方法的返回值为Optional,我本是想直接在Optional进行继承并拓展,无奈它是一个final
  • 我想,就这样眼睁睁看着Hutool中的OptionalBean被废弃,不如让它梅开二度,在Hutool的新版本迎来第二春!

修改描述(包括说明bug修复或者添加新特性)

  1. [bug修复] balabala……
  2. [新特性]
  • 对原生Optional的使用区别不大,学习成本低
  • 注释全都汉化并带理解(累瘫)
  • 相比与Optional的新特性都包含在测试用例中
  • ofBlankAble函数基于ofNullable的逻辑下,额外进行了空字符串判断
		// ofBlankAble相对于ofNullable考虑了字符串为空串的情况
		String hutool = OptionalBean.ofBlankAble("").orElse("hutool");
		Assert.assertEquals("hutool", hutool);
  • 原版Optional有区别的是,get不会抛出NoSuchElementException
  • 如果想使用原版Optional中的get这样,获取一个一定不为空的值,则应该使用orElseThrow
		// 和原版Optional有区别的是,get不会抛出NoSuchElementException
		// 如果想使用原版Optional中的get这样,获取一个一定不为空的值,则应该使用orElseThrow
		Object opt = OptionalBean.ofNullable(null).get();
		Assert.assertNull(opt);
  • 将jdk11 Optional中的新函数isEmpty,直接照搬了过来
		// 这是jdk11 Optional中的新函数,直接照搬了过来
		// 判断包裹内元素是否为空,注意并没有判断空字符串的情况
		boolean isEmpty = OptionalBean.empty().isEmpty();
		Assert.assertTrue(isEmpty);
  • 将jdk9 Optional中的新函数ifPresentOrElse,直接照搬了过来
		// 这是jdk9中的新函数,直接照搬了过来
		// 存在就打印对应的值,不存在则用{@code System.err.println}打印另一句字符串
		OptionalBean.ofNullable("Hello Hutool!").ifPresentOrElse(System.out::println, () -> System.err.println("Ops!Something is wrong!"));
		OptionalBean.empty().ifPresentOrElse(System.out::println, () -> System.err.println("Ops!Something is wrong!"));
  • 新增了peek函数,相当于ifPresent的链式调用(个人常用)
		User user = new User();
		// 相当于ifPresent的链式调用
		OptionalBean.ofNullable("hutool").peek(user::setUsername).peek(user::setNickname);
		Assert.assertEquals("hutool", user.getNickname());
		Assert.assertEquals("hutool", user.getUsername());

		// 注意,传入的lambda中,对包裹内的元素执行赋值操作并不会影响到原来的元素
		String name = OptionalBean.ofNullable("hutool").peek(username -> username = "123").peek(username -> username = "456").get();
		Assert.assertEquals("hutool", name);
  • 将jdk9 Optional中的新函数or,直接照搬了过来
		// 这是jdk9 Optional中的新函数,直接照搬了过来
		// 给一个替代的Opt
		String str = OptionalBean.<String>ofNullable(null).or(() -> OptionalBean.ofNullable("Hello hutool!")).map(String::toUpperCase).orElseThrow();
		Assert.assertEquals("HELLO HUTOOL!", str);

		User user = User.builder().username("hutool").build();
		OptionalBean<User> userOptionalBean = OptionalBean.of(user);
		// 获取昵称,获取不到则获取用户名
		String name = userOptionalBean.map(User::getNickname).or(() -> userOptionalBean.map(User::getUsername)).get();
		Assert.assertEquals("hutool", name);
  • 对orElseThrow进行了重载,支持 双冒号+自定义提示语 写法,比原来的
    orElseThrow(() -> new IllegalStateException("Ops!Something is wrong!"))

更加优雅,修改后写法为:

    orElseThrow(IllegalStateException::new, "Ops!Something is wrong!")

测试用例:

		// 获取一个不可能为空的值,否则抛出NoSuchElementException异常
		Object obj = OptionalBean.ofNullable(null).orElseThrow();
		// 获取一个不可能为空的值,否则抛出自定义异常
		Object assignException = OptionalBean.ofNullable(null).orElseThrow(IllegalStateException::new);
		// 获取一个不可能为空的值,否则抛出带自定义消息的自定义异常
		Object exceptionWithMessage = OptionalBean.empty().orElseThrow(IllegalStateException::new, "Ops!Something is wrong!");