Hutool Hutool
(opens new window)
🏡首页
📖指南
  • 核心(Hutool-core)
  • 配置文件(Hutool-setting)
  • 日志(Hutool-log)
  • 缓存(Hutool-cache)
  • JSON(Hutool-json)
  • 加密解密(Hutool-crypto)
  • DFA查找(Hutool-dfa)
  • 数据库(Hutool-db)
  • HTTP客户端(Hutool-http)
  • 定时任务(Hutool-cron)
  • 扩展(Hutool-extra)
  • 布隆过滤(Hutool-bloomFilter)
  • 切面(Hutool-aop)
  • 脚本(Hutool-script)
  • Office文档操作(Hutool-poi)
  • 系统调用(Hutool-system)
  • 图形验证码(Hutool-captcha)
  • 网络Socket(Hutool-socket)
  • JWT(Hutool-jwt)
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
(opens new window)
🏡首页
📖指南
  • 核心(Hutool-core)
  • 配置文件(Hutool-setting)
  • 日志(Hutool-log)
  • 缓存(Hutool-cache)
  • JSON(Hutool-json)
  • 加密解密(Hutool-crypto)
  • DFA查找(Hutool-dfa)
  • 数据库(Hutool-db)
  • HTTP客户端(Hutool-http)
  • 定时任务(Hutool-cron)
  • 扩展(Hutool-extra)
  • 布隆过滤(Hutool-bloomFilter)
  • 切面(Hutool-aop)
  • 脚本(Hutool-script)
  • Office文档操作(Hutool-poi)
  • 系统调用(Hutool-system)
  • 图形验证码(Hutool-captcha)
  • 网络Socket(Hutool-socket)
  • JWT(Hutool-jwt)
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
  • 快速入门

  • 核心(Hutool-core)

    • AI(Hutool-ai)

    • 克隆

    • 类型转换

    • 日期时间

    • IO流相关

    • 工具类

    • 语言特性

    • JavaBean

      • 概述
      • Bean工具-BeanUtil
      • DynaBean
      • 表达式解析-BeanPath
      • Bean描述-BeanDesc
      • 空检查属性获取-Opt
        • 介绍
        • 使用
        • 学习:
    • 集合类

    • Map

    • Codec编码

    • 文本操作

    • 注解

    • 比较器

    • 异常

    • 数学

    • 线程和并发

    • 图片

    • 网络

    • 源码编译

  • 配置文件(Hutool-setting)

  • 日志(Hutool-log)

  • 缓存(Hutool-cache)

  • JSON(Hutool-json)

  • 加密解密(Hutool-crypto)

  • DFA查找(Hutool-dfa)

  • 数据库(Hutool-db)

  • HTTP客户端(Hutool-http)

  • 定时任务(Hutool-cron)

  • 扩展(Hutool-extra)

  • 布隆过滤(Hutool-bloomFilter)

  • 切面(Hutool-aop)

  • 脚本(Hutool-script)

  • Office文档操作(Hutool-poi)

  • 系统调用(Hutool-system)

  • 图形验证码(Hutool-captcha)

  • 网络Socket(Hutool-socket)

  • JWT(Hutool-jwt)

  • 指南
  • 核心(Hutool-core)
  • JavaBean
Hutool
2023-03-28
目录

空检查属性获取-Opt

特别赞助 by:

# 介绍

在嵌套对象的属性获取中,由于子对象无法得知是否为null,每次获取属性都要检查属性对象是否为null,使得代码会变得特备臃肿,因此使用Opt来优雅的链式获取属性对象值。

声明:此类的作者:阿超 (opens new window) ,PR来自:https://gitee.com/dromara/hutool/pulls/426

# 使用

我们先定义一个嵌套的Bean:

// Lombok注解
@Data
public static class User {
	private String name;
	private String gender;
	private School school;
	
	@Data
	public static class School {
		private String name;
		private String address;
	}
}

假设我们想获取address属性,则:

User user = new User();
user.setName("hello");

// null
String addressValue = Opt.ofNullable(user)
		.map(User::getSchool)
		.map(User.School::getAddress).get();

由于school对象的值为null,一般直接获取会报空指针,使用Opt即可避免判断。

  • ofBlankAble函数基于ofNullable的逻辑下,额外进行了空字符串判断
// ofBlankAble相对于ofNullable考虑了字符串为空串的情况
String hutool = Opt.ofBlankAble("").orElse("hutool");
Assert.equals("hutool", hutool);
  • 和原版Optional有区别的是,Opt.get()不会抛出NoSuchElementException
  • 如果想像原版Optional中的get那样,获取一个一定不为空的值,则应该使用orElseThrow
Object opt = Opt.ofNullable(null).get();
Assert.isNull(isEmpty);
  • 这是参考了jdk11 Optional中的新函数isEmpty,用于判断不存在值的情况
// 判断包裹内元素是否为空,注意并没有判断空字符串的情况
boolean isEmpty = Opt.empty().isEmpty();
Assert.isTrue(isEmpty);
  • 灵感来源于jdk9 Optional中的新函数ifPresentOrElse,用于 存在值时执行某些操作,不存在值时执行另一个操作,支持链式编程
// 存在就打印对应的值,不存在则用System.err.println打印另一句字符串
Opt.ofNullable("Hello Hutool!").ifPresentOrElse(System.out::println, () -> System.err.println("Ops!Something is wrong!"));
Opt.empty().ifPresentOrElse(System.out::println, () -> System.err.println("Ops!Something is wrong!"));
  • 新增了peek函数,相当于ifPresent的链式调用(个人常用)
User user = new User();
// 相当于ifPresent的链式调用
Opt.ofNullable("hutool").peek(user::setUsername).peek(user::setNickname);
Assert.equals("hutool", user.getNickname());
Assert.equals("hutool", user.getUsername());

// 注意,传入的lambda中,对包裹内的元素执行赋值操作并不会影响到原来的元素
String name = Opt.ofNullable("hutool").peek(username -> username = "123").peek(username -> username = "456").get();
Assert.equals("hutool", name);
  • 灵感来源于jdk11 Optional中的新函数or,用于值不存在时,用别的Opt代替
// 给一个替代的Opt
String str = Opt.<String>ofNullable(null).or(() -> Opt.ofNullable("Hello hutool!")).map(String::toUpperCase).orElseThrow();
Assert.equals("HELLO HUTOOL!", str);

User user = User.builder().username("hutool").build();
Opt<User> userOpt = Opt.of(user);
// 获取昵称,获取不到则获取用户名
String name = userOpt.map(User::getNickname).or(() -> userOpt.map(User::getUsername)).get();
Assert.equals("hutool", name);
  • 对orElseThrow进行了重载,支持 双冒号+自定义提示语 写法,比原来的更加优雅。

原来的写法:

orElseThrow(() -> new IllegalStateException("Ops!Something is wrong!"))

修改后写法:

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

# 学习:

经常有朋友问我,你这个Opt,参数怎么都是一些lambda,我怎么知道对应的lambda怎么写呢?

这函数式编程,真是一件美事啊~

对于这种情况,我们依靠我们强大的idea即可

例如此处我写到这里不会写了

User user = new User();
Opt.ofNullable(user).map(|光标停在此处)
// idea会提示方法参数,如果没显示,光标放到括号里按ctrl+p主动呼出            
        |Function<? super User,?> mapper|

这里idea为我们提示了参数类型,可这个Function我也不知道它是个什么

实际上,我们new一个就好了

Opt.ofNullable(user).map(new Fun)
                            |Function<User, Object>{...} (java.util.function)   |  <-戳我
                            |Func<P,R> cn.hutool.core.lang.func                 |

这里idea提示了剩下的代码,我们选Function就行了,接下来如下:

Opt.ofNullable(user).map(new Function<User, Object>() {
})

此处开始编译报错了,不要着急,我们这里根据具体操作选取返回值

例如我这里是想判断user是否为空,不为空时调用getSchool,从而获取其中的返回值String类型的school

我们就如下写法,将第二个泛型,也就是象征返回值的泛型改为String:

Opt.ofNullable(user).map(new Function<User, String>() {
})

然后我们使用idea的修复所有,默认快捷键alt+回车

Opt.ofNullable(user).map(new Function<User, String>() {
})                                                | 💡 Implement methods                  |  <-选我
                                                  | ✍  Introduce local variable          |
                                                  | ↩  Rollback changes in current line   |

选择第一个Implement methods即可,这时候弹出一个框,提示让你选择你想要实现的方法

这里就选择我们的apply方法吧,按下一个回车就可以了,或者点击选中apply,再按一下OK按钮

    ||IJ| Select Methods to Implement                        X |
    |                                                          |
    | 👇  ©  |  ↹  ↸                                          |
    | -------------------------------------------------------- |
    | | java.util.function.Function                            |
    | | ⒨ 🔓 apply(t:T):R                                     |      <-选我选我
    | | ⒨ 🔓 compose(before:Function<? super V,? extents T):Fu|
    | | ⒨ 🔓 andThen(after:Function<? super R,? extends V>):Fu|
    | |                                                        |
    | | ========================================               |                                        
    | -------------------------------------------------------- |
    |  ☐ Copy JavaDoc                                          |
    |  ☑ Insert @Override               |  OK  |  | CANCEL |   |     <-选完点我点我

此时此刻,代码变成了这样子

Opt.ofNullable(user).map(new Function<User, String>() {
    @Override
    public String apply(User user) {
        return null;
    }
})

这里重写的方法里面就写你自己的逻辑(别忘了补全最后小括号后面的分号)

Opt.ofNullable(user).map(new Function<User, String>() {
    @Override
    public String apply(User user) {
        return user.getSchool();
    }
});

我们可以看到,上边的new Function<User, String>()变成了灰色

我们让光标移动到灰色字符上面,按一下alt+enter(回车)

Opt.ofNullable(user).map(new Function<User, String>() {
    @Override                              | 💡 Replace with lambda             > |  <-选我啦
    public String apply(User user) {       | 💡 Replace with method reference   > |
        return user.getSchool();           | 💎 balabala...                     > |
    }
});

选择第一个Replace with lambda,就会自动缩写为lambda啦

Opt.ofNullable(user).map(user1 -> user1.getSchool());

如果选择第二个,则会缩写为我们双冒号格式

Opt.ofNullable(user).map(User::getSchool);

看,是不是很简单!

上次更新: 2025/05/21, 11:39:56
Bean描述-BeanDesc
概述

← Bean描述-BeanDesc 概述→

Theme by Vdoing | Copyright © 2023-2025 Hutool | MulanPSL-2.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×