遇到空指针(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

相关文章
|
2月前
|
Java 编译器 程序员
小心踩坑!s1 = s1 + 1 和 s1 += 1 的区别你真的懂吗?
小米,一位29岁的技术爱好者,通过一个Java面试题解析了隐式类型转换与赋值运算符特性的知识点。题目涉及`short s1 = 1; s1 = s1 + 1;`与`short s1 = 1; s1 += 1;`的区别,前者因类型不匹配报错,后者则因`+=`运算符的隐式类型转换功能而成功编译。小米通过故事化讲解,深入浅出地解释了Java中数据类型转换的规则及其背后的逻辑,帮助读者更好地理解和记忆这一知识点。
28 3
|
2月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
8月前
|
程序员 开发工具 Python
最全学Python有什么用?看完这些你肯定明白_学pysion的作用,2024年最新字节跳动面试严格吗
最全学Python有什么用?看完这些你肯定明白_学pysion的作用,2024年最新字节跳动面试严格吗
最全学Python有什么用?看完这些你肯定明白_学pysion的作用,2024年最新字节跳动面试严格吗
毕业两年了,又重学了一遍二叉树遍历的三种方式
毕业两年了,又重学了一遍二叉树遍历的三种方式
151 0
毕业两年了,又重学了一遍二叉树遍历的三种方式
|
Java 程序员
学妹问我Java异常是怎么回事,讲了半夜才明白,速度收藏!!!记得点赞和关注
异常是Java开发中常见的,也是程序最不愿意看到的,因为有异常基本上就代表我们写的代码有bug,很烦,游戏服务端有异常上报系统,每当半夜收到异常上报都慌的一笔。今天就扒一扒异常,开始走起。
151 0
学妹问我Java异常是怎么回事,讲了半夜才明白,速度收藏!!!记得点赞和关注

相关实验场景

更多