“价值百万的重大失误”---NullPointerException,现在再也不怕了

简介: “价值百万的重大失误”---NullPointerException,现在再也不怕了

作为Java程序员曾经遭遇过NullPointerException,毫无疑问,对任何一位Java程序员来说,无论是初出茅庐的新人,还是久经江湖的专家,NullPointerException都是他心中的痛,可是我们又无能为力,因为这就是我们为了使用方便甚至不可避免的像null引用这样的构造所付出的代价。

历史解决NullPointerException的办法

举例说明

public class Person {
    private Car car;
    public Car getCar() { return car; }
}
public class Car {
    private Insurance insurance;
    public Insurance getInsurance() { return insurance; }
}
public class Insurance {
    private String name;
    public String getName() { return name; }
}
AI 代码解读

我们该怎么获取到保险公司名字呢?

public String getCarInsuranceName(Person person) {
    return person.getCar().getInsurance().getName();
}
AI 代码解读

这段代码看起来相当正常,但是现实生活中很多人没有车。所以调用getCar方法的结果会怎样呢?在实践中,一种比较常见的做法是返回一个null引用,表示该值的缺失,即用户没有车。而接下来,对getInsurance的调用会返回null引用的insurance,这会导致运行时出现一个NullPointerException,终止程序的运行。但这还不是全部。如果返回的person值为null会怎样?如果getInsurance的返回值也是null,结果又会怎样?

所以正确的写法应该是:

public String getCarInsuranceName(Person person) {
    if (person != null) {
        Car car = person.getCar();
        if (car != null) {
            Insurance insurance = car.getInsurance();
            if (insurance != null) {
                return insurance.getName();
            }
        }
    }
    return "Unknown";
}
AI 代码解读

......我为了得到一个名字写了这么多,如果你们公司是按代码行数发工资的话,其实这样也挺好的(哈哈)

null带来的种种问题

它是错误之源

NullPointerException是目前Java程序开发中最典型的异常。

它会使你的代码膨胀

它让你的代码充斥着深度嵌套的null检查,代码的可读性糟糕透顶。

它自身是毫无意义的

null自身没有任何的语义,尤其是,它代表的是在静态类型语言中以一种错误的方式对缺失变量值的建模。

它破坏了Java的哲学

Java一直试图避免让程序员意识到指针的存在,唯一的例外是:null指针。

它在Java的类型系统上开了个口子。

null并不属于任何类型,这意味着它可以被赋值给任意引用类型的变量。这会导致问题,原因是当这个变量被传递到系统中的另一个部分后,你将无法获知这个null变量最初的赋值到底是什么类型。

如何解决---Optional

举例说明

public class Person {
    private Optional<Car> car;
    public Optional<Car> getCar() { return car; }
}
public class Car {
    private Optional<Insurance> insurance;
    public Optional<Insurance> getInsurance() { return insurance; }
}
public class Insurance {
    private String name;
    public String getName() { return name; }
}
AI 代码解读

我们该怎么获取到保险公司名字呢?

public String getCarInsuranceName(Optional<Person> person) {
    return person.flatMap(Person::getCar)
                 .flatMap(Car::getInsurance)
                 .map(Insurance::getName)
                 .orElse("Unknown");
}
AI 代码解读

是不是很清晰很舒服
640.png

应用Optional的几种模式

声明一个空的Optional

通过静态工厂方法Optional.empty,创建一个空的Optional对象:

Optional<Car> optCar = Optional.empty();
AI 代码解读

据一个非空值创建Optional

使用静态工厂方法Optional.of,依据一个非空值创建一个Optional对象:

Optional<Car> optCar = Optional.of(car);
AI 代码解读

声明一个空的Optional

使用静态工厂方法Optional.ofNullable,可以创建一个允许null值的Optional对象:

Optional<Car> optCar = Optional.ofNullable(car);
AI 代码解读

默认行为及解引用Optional对象

get()

最简单但又最不安全的方法。如果变量存在,它直接返回封装的变量值,否则就抛出一个NoSuchElementException异常。

orElse(T other)

它允许你在Optional对象不包含值时提供一个默认值。

orElseGet(Supplier<? extends T> other)

orElse方法的延迟调用版,Supplier方法只有在Optional对象不含值时才执行调用。

orElseThrow(Supplier<? extends X> exceptionSupplier)

和get方法非常类似,它们遭遇Optional对象为空时都会抛出一个异常,但是使用orElseThrow你可以定制希望抛出的异常类型。

ifPresent(Consumer<? super T>)

能在变量值存在时执行一个作为参数传入的方法,否则就不进行任何操作。

默认行为及解引用Optional对象

640.png

640.jpg

总结

  1. null引用在历史上被引入到程序设计语言中,目的是为了表示变量值的缺失。
  2. Java 8中引入了一个新的类java.util.Optional,对存在或缺失的变量值进行建模。
  3. 你可以使用静态工厂方法Optional.empty、Optional.of以及Optional.ofNullable创建Optional对象。
  4. 使用Optional会迫使你更积极地解引用Optional对象,以应对变量值缺失的问题,最终,你能更有效地防止代码中出现不期而至的空指针异常。
  5. 使用Optional能帮助你设计更好的API,用户只需要阅读方法签名,就能了解该方法是否接受一个Optional类型的值。
目录
打赏
0
0
0
0
2
分享
相关文章
阿里员工吐槽:工作压力真的大,年假都没心情用,后悔来阿里
阿里巴巴是当下国内最顶尖的互联网公司之一,经过19年的发展,如今的阿里已经从单纯的电子商务公司过渡到了综合型的超级巨头。如今阿里旗下的阿里云已经成为了国内第一,世界第三的云计算公司。
4266 0
|
10月前
|
程序员缓解工作压力有哪些小窍门
程序员合理释放工作压力和情绪至关重要,需要找到合适自己的节奏和方式
116 0
支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!
支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!
175 0
支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!
当在线购物遇上数据危机:Hibernate 事务管理如何力挽狂澜,确保每一次交易都万无一失?
【8月更文挑战第31天】数据一致性和事务管理对任何企业级应用至关重要,尤其是在使用 Hibernate 时。本文通过在线购物系统的具体案例,介绍了正确管理事务的重要性。以 `Product` 和 `Order` 实体为例,阐述了如何通过编程式或声明式事务管理(如 Java 代码示例中的 `@Transactional` 注解)来确保数据一致性。正确配置事务能显著提升应用质量和系统稳定性。
52 0
程序员新人频繁使用count(*),被组长批评后怒怼:性能并不拉垮!
程序员新人频繁使用count(*),被组长批评后怒怼:性能并不拉垮!
还在因为写项目函数太多而烦恼?C++模板一文带你解决难题
还在因为写项目函数太多而烦恼?C++模板一文带你解决难题

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等