遇到空指针(npe)切莫慌 ✨ jdk 8中有妙招 ✨ 每日积累

简介: 遇到空指针(npe)切莫慌 ✨ jdk 8中有妙招 ✨ 每日积累

项目中空指针的烦恼


不管大大小小的项目,只要一个不注意,就会有java.lang.NullPointerException的异常抛出来,自己在测试的时候还好,但是线上项目一旦空指针切没有处理,那就问题大了。所以我们单测的开发好的需求的时候尽量吧所有的场景都测试一下。在 Java 8 之前,任何访问对象方法或属性的调用都可能导致 NullPointerException:,jdk8之后中有Class Optional这个类,能帮助我们更好的解决空指针问题。这个简单而强大的类有助于创建简单、可读性更强、比对应程序错误更少的程序。


api解释如下

可能包含或不包含非空值的容器对象。 如果一个值存在, isPresent()将返回true和get()将返回值。


提供依赖于存在或不存在包含值的其他方法,例如orElse() (如果值不存在则返回默认值)和ifPresent() (如果值存在则执行代码块)。


这是一个value-based课; 使用身份敏感的操作(包括引用相等(的==上的实例),标识哈希码,或同步) Optional可具有不可预测的结果,应当避免。


方法摘要

Modifier and Type

Method and Description
static <T> Optional<T> empty()返回一个空的 Optional实例。
boolean equals(Object obj)指示某个其他对象是否等于此可选项。
Optional<T> filter(Predicate<? super T> predicate)如果一个值存在,并且该值给定的谓词相匹配时,返回一个 Optional描述的值,否则返回一个空的 Optional 
<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)如果一个值存在,应用提供的 Optional映射函数给它,返回该结果,否则返回一个空的 Optional 
T

get()如果 Optional中有一个值,返回值,否则抛出 NoSuchElementException

int

hashCode()返回当前值的哈希码值(如果有的话),如果没有值,则返回0(零)。

void ifPresent(Consumer<? super T> consumer)如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。
boolean isPresent()返回 true如果存在值,否则为 false 
<U>Optional<U> map(Function<? super T,? extends U> mapper)如果存在一个值,则应用提供的映射函数,如果结果不为空,则返回一个 Optional结果的 Optional
static <T> Optional<T> of(T value)返回具有 Optional的当前非空值的Optional。
static <T> Optional<T> ofNullable(T value)返回一个 Optional指定值的Optional,如果非空,则返回一个空的 Optional 
T orElse(T other)返回值如果存在,否则返回 other 
T

orElseGet(Supplier<? extends T> other)返回值(如果存在),否则调用 other并返回该调用的结果。

<X extends Throwable>T orElseThrow(Supplier<? extends X> exceptionSupplier)返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。
String toString()返回此可选的非空字符串表示,适用于调试。


常用方法


创建Optional对象的方法:
 Optional.of(T t):创建一个Optional实例,t必须非空
 Optional.empty():创建一个空Optional实例
 Optional.ofNullable(T t):创建一个Optional实例,t可以为null
判断Optional对象中是否有对象:
 boolean isPresent():判断Optional容器中是否有对象
 void ifPresent(Consumer<? super T> consumer):如果存在一个值,则应用提供的映射函数,如果结果不为空,则返回一个 Optional结果的 Optional。
获取Optional容器中的对象:
 T get():如果调用对象包含值,返回该值,否则抛异常
 T orElse(T t1):如果调用容器中有值,则返回容器中的值,否则返回t1对象
 T orElseGet(Supplier<? extends T> other):如果有值则将其返回,否则返回由Supplier接口实现提供的对象
 T orElseThrow(Supplier<? extends X> exceptionSupplier):如果有值则返回,否则抛出由Supplier接口实现提供的异常


项目中可以组合使用的方法


如果项目中的一些参数不确定有值则可以这样使用


示例代码

import java.util.Optional;
import java.util.function.Supplier;
public class TestOptional {
    public static void main(String[] args) {
        UserTest userTest = new UserTest();
        userTest.setUserId("1");
        //isPresent():判断Optional容器中是否有对象
        String userName = userTest.getUserName().isPresent() == true ? userTest.getUserName().get() : "defaultName";
        System.out.println(userName);
        //orElse(T t1)
        System.out.println(userTest.getUserName().orElse("MrLi"));
        //orElseGet(Supplier<? extends T> other):如果有值则返回,没值则执行函数
        final String s = userTest.getUserName().orElseGet(new Supplier<String>() {
            @Override
            public String get() {
                return userTest.getUserName().orElse("Jhon") + "-test";
            }
        });
        System.out.println(s);
        //orElseThrow:在报错时可抛出异常供我们捕获进行处理
        try {
            userTest.getUserName().orElseThrow(() -> new NullPointerException());
        } catch (Throwable throwable) {
            //do something
            System.out.println("空指针异常");
        }
        //高级用法:嵌套类中的链式调用
        Employee employee = new Employee();
        employee.setUser(new Employee.User("MrWan"));
        String employeeName = Optional.ofNullable(employee)
                .flatMap(employeeTest -> employeeTest.getUser())
                .map(employeeTest -> {
                    employeeTest.setName("MrQing");
                    return employeeTest;
                }).get().getName().get();
        System.out.println(employeeName);
    }
}
class UserTest{
    private String userName;
    private String userId;
    //get()使用Optional<T>封装一下
    public Optional<String> getUserName() {
        return Optional.ofNullable(userName);
    }
    public Optional<String> getUserId() {
        return Optional.ofNullable(this.userId);
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    @Override
    public String toString() {
        return "UserTest{" +
                "userName='" + userName + '\'' +
                ", userId='" + userId + '\'' +
                '}';
    }
}
class Employee{
    private User user;
    public Optional<User> getUser() {
        return Optional.ofNullable(user);
    }
    public void setUser(User user) {
        this.user = user;
    }
    static class User{
        private String name;
        public User(String name) {
            this.name = name;
        }
        public Optional<String> getName() {
            return Optional.ofNullable(name);
        }
        public void setName(String name) {
            this.name = name;
        }
    }
}

运行结果

1.png

相关文章
|
Python
python os.listdir的替代方案os.scandir
python os.listdir的替代方案os.scandir
1026 0
|
资源调度 jenkins 持续交付
jenkins 自动安装nodejs16.16.0版本报错处理
jenkins 自动安装nodejs16.16.0版本报错处理
1147 0
|
数据采集 机器学习/深度学习 人工智能
《智启新材:人工智能重塑分子结构设计蓝图》
在科技飞速发展的今天,新材料研发竞争激烈,人工智能(AI)以其强大的数据分析和算法能力,为分子结构设计带来革命性突破。传统方法耗时长、成功率低,而AI能快速处理海量数据,挖掘规律,构建精准模型,大幅缩短研发周期,提高成功率。无论是在药物研发还是工业材料领域,AI均展现出巨大潜力,如优化航空航天材料性能、设计新型碳纤维复合材料等。尽管面临数据质量和可解释性挑战,AI在新材料领域的前景依然广阔,正引领材料创新新时代,推动能源革命与物联网发展。
256 9
|
传感器 机器学习/深度学习 弹性计算
Agent与大模型的区别
本文详细对比了人工智能领域的两个重要概念——Agent和大模型。大模型如GPT-3、BERT等,擅长自然语言处理任务,如文本生成、翻译等;Agent则是自主的软件实体,能够在特定环境中感知、决策并执行任务,如管理日程、控制智能家居等。文章介绍了它们的定义、功能、技术架构及应用场景,并总结了两者的核心差异和未来发展方向。
9289 25
|
Java 数据库连接 数据库
springboot启动配置文件-bootstrap.yml常用基本配置
以上是一些常用的基本配置项,在实际应用中可能会根据需求有所变化。通过合理配置 `bootstrap.yml`文件,可以确保应用程序在启动阶段加载正确的配置,并顺利启动运行。
1756 2
|
Prometheus 监控 Cloud Native
Prometheus 社区与生态发展
【8月更文第29天】Prometheus 是一个开源的监控系统和时间序列数据库,以其简单易用、高性能的特点受到了广泛欢迎。自 2012 年成立以来,Prometheus 社区迅速壮大,形成了一个庞大且活跃的技术生态系统。本文将探讨 Prometheus 社区的发展趋势、相关项目和工具,以及如何参与贡献。
466 1
layui的富文本编辑器layedit设置禁用状态
layui的富文本编辑器layedit设置禁用状态
238 0
|
安全 API
Vue3 proxy 解决跨域
jsonp 这种方式在之前很常见,他实现的基本原理是利用了HTML里script元素标签没有跨域限制 动态创建script标签,将src作为服务器地址,服务器返回一个callback接受返回的参数
744 0
Vue3 proxy 解决跨域
|
存储 SQL 测试技术
SqlAlchemy 2.0 中文文档(三十一)(1)
SqlAlchemy 2.0 中文文档(三十一)
212 1
|
缓存 Oracle 关系型数据库
Oracle中的触发器与序列:自增列的魔法组合
【4月更文挑战第19天】Oracle数据库中,通过触发器和序列的组合可实现自增列功能。序列充当自动计数器,提供递增数值,而触发器则在插入新记录时自动分配序列值。创建序列如`CREATE SEQUENCE emp_seq START WITH 1 INCREMENT BY 1 NOCACHE`,然后创建触发器`TRIGGER trg_employees_before_insert`在`BEFORE INSERT`时将序列的下一个值赋予`employee_id`。这种方式使得在插入记录时无需手动设置ID,提高了效率。但使用时需注意序列状态、并发性和性能优化。