将 null 传递给 [已关闭] 方法

2022-09-02 09:40:39

我正在阅读优秀的清洁代码

一个讨论是关于将 null 传递到方法中。

public class MetricsCalculator {
    public double xProjection(Point p1, Point p2) {
        return (p2.x - p1.x) * 1.5;
    }
}
...
calculator.xProjection(null, new Point(12,13));

它代表了处理此问题的不同方法:

public double xProjection(Point p1, Point p2) {
    if (p1 == null || p2 == null) {
        throw new IllegalArgumentException("Invalid argument for xProjection");
    }
    return (p2.x - p1.x) * 1.5;
}

public double xProjection(Point p1, Point p2) {
    assert p1 != null : "p1 should not be null";
    assert p2 != null : "p2 should not be null";
    return (p2.x - p1.x) * 1.5;
}

我更喜欢断言方法,但我不喜欢断言默认关闭的事实。

这本书最后说:

在大多数编程语言中,没有好的方法来处理调用方意外传递的 null。因为是这种情况,所以合理的方法是禁止在默认情况下传递 null。

它并没有真正进入你如何执行这个限制?

你们中是否有人有强烈的意见。


答案 1

一般规则是,如果你的方法不需要参数,那么你应该抛出System.ArgumentNullException。正确抛出不仅可以保护您免受资源损坏和其他不良事物的影响,还可以作为代码用户的指南,节省调试代码所花费的时间。nullException

另请阅读有关防御性编程的文章


答案 2

断言的使用和异常的抛出都是有效的方法。这两种机制都可用于指示编程错误,而不是运行时错误,就像这里的情况一样。

  • 断言具有性能优势,因为它们通常在生产系统上被禁用。
  • 异常具有安全的优势,因为始终执行检查。

选择实际上取决于项目的开发实践。整个项目需要决定一个断言策略:如果选择是在所有开发期间启用断言,那么我会说使用断言来检查这种无效参数 - 在生产系统中,由于编程错误而引发的NullPointerException无论如何都不太可能以有意义的方式被捕获和处理,因此就像断言一样。

但实际上,我知道很多开发人员不相信断言会在适当的时候启用,因此选择抛出NullPointerException的安全性。

当然,如果您无法为代码强制实施策略(例如,如果您正在创建一个库,因此取决于其他开发人员如何运行您的代码),则应选择为库的 API 的那些方法抛出 NullPointerException 的安全方法。