我们是不是应该总是在第一行检查java中方法的每个参数是不是为null?

Posted

技术标签:

【中文标题】我们是不是应该总是在第一行检查java中方法的每个参数是不是为null?【英文标题】:Should we always check each parameter of method in java for null in the first line?我们是否应该总是在第一行检查java中方法的每个参数是否为null? 【发布时间】:2011-07-07 13:47:23 【问题描述】:

每个方法都接受一组参数值。我们应该始终验证输入参数的非空性还是允许代码以经典的RunTimeException 失败?

我见过很多代码,人们并没有真正检查输入参数的空性,而只是使用参数编写业务逻辑。最好的方法是什么?

void public( String a, Integer b, Object c)

  if( a == null || b == null || c == null)
  
    throw new RunTimeException("Message...");
  
  .....business logic.....

【问题讨论】:

Where to check if an object is null or not? 的可能重复项 另一个问题是关于.net,但本质上是相同的。 当前的答案都没有提到使用注释和静态分析,例如 FindBugs @NonNull、@CheckForNull 等。此外,虽然这不是上述 .Net 问题的重复,但很可能在 *** 中至少被覆盖一次。 【参考方案1】:

我认为这样做没有什么意义。您只是在复制您第一次尝试在 abc 上操作时免费获得的行为。

【讨论】:

【参考方案2】:

这取决于你的代码试图做什么以及你想要抛出Exception 的情况。有时,如果您的方法无法使用空值正常工作,您会希望您的方法始终抛出异常。如果你的方法可以处理空值,那么它可能不需要抛出异常。

添加太多已检查的异常会使代码变得非常复杂和复杂。这就是它们没有包含在 C# 中的原因。

【讨论】:

【参考方案3】:

最好的方法是仅在必要时检查

如果你的方法是private,例如,你知道没有其他人在使用它,并且你知道你没有传入任何空值,那么就没有必要再次检查了。

如果你的方法是public,谁知道你的 API 的用户会尝试做什么,所以最好检查一下。

如果有疑问,请检查

但是,如果您能做的最好的事情是抛出NullPointerException,那么可能不想检查。例如:

int getStringLength(String str) 
  return str.length();

即使你检查了null,一个合理的选择是抛出一个NullPointerExceptionstr.length() 无论如何都会为你做。

【讨论】:

我不建议依靠自动 NullPointerException 来代替显式参数验证。两个原因:(a) 验证应始终尽可能早地进行(想想方法在遇到 NPE 之前更改某些状态)和 (b) 代码可支持性。 X 类主体中的 NPE 将首先转到 X 类的所有者,因为它看起来像是实现中的错误。但是,如果您显式检查 args 是否为 null 并抛出 IllegalArgumentException(也类似于 NPE 的 RuntimeException),那么很明显问题出在 X 类的调用者上。【参考方案4】:

没有。假设参数不为 null 并且否则将抛出 NullPointerException 是标准的。如果你的方法允许参数为空,你应该在你的 api 中声明。

【讨论】:

【参考方案5】:

这取决于您是否期望您的任何参数是null - 更准确地说,如果某些参数是null,您的方法是否仍然可以做出正确的决定。

如果没有,最好检查null 并引发异常,否则你会得到一个NullPointerException,你不应该捕获它,因为它的出现总是表明你忘记检查你的变量你的代码。 (如果你抓住它,你可能会错过它被抛出的其他事件,并且你可能会引入错误)。

另一方面,如果您抛出 RunTimeException 或其他一些自定义异常,您可以在上游的某个地方处理它,这样您就可以更好地控制发生的事情。

【讨论】:

【参考方案6】:

不,你不应该普遍这样做。

我的偏好依次是:

    对 null 做一些明智的事情。明智的做法完全取决于具体情况,但抛出自定义异常不应该是您的首选。 使用断言检查 null 并彻底测试,消除任何产生 null 输入的情况,因为 - 也就是错误。 对于公共 API,记录不允许 null 并让它失败并返回 NPE。

【讨论】:

@downvoter 没有解释?只是不喜欢我的短臂?【参考方案7】:

你不应该抛出运行时异常,除非它确实是系统运行的致命条件,例如缺少关键的运行时参数,但即使这样也是有问题的,因为系统不应该启动。

什么是业务规则?该字段是否允许为空?不是吗?

在任何情况下,在您尝试对传入的任何参数进行操作之前检查它们是否为空值始终是一种好习惯,因此当有人向您传递错误数据时,您不会收到NullPointerExceptions

【讨论】:

【参考方案8】:

如果您不知道是否应该这样做,那么很有可能,您不需要这样做。

JDK 资源和 Joshua Bloch 的书是值得效仿的可怕示例,因为它们针对的是非常不同的受众。我们中有多少人正在为数百万程序员编写公共 API?

【讨论】:

【参考方案9】:

Java 的一个不幸方面是引用可以是null,并且无法在语言中指定它们不是。

所以通常是的,不要对null 做出解释,也不要陷入以后可能会抛出 NPE 的情况。

JSR305(现在不活动)允许您注释参数以声明它们不应该被赋予nulls。

void fn(@Nonnull String a, @Nonnull Integer b, @Nonnull Object c) 

冗长,但那是适合您的 Java。还有其他注释库和检查器可以做很多相同的事情,但都是非标准的。

(注意大小写:当“non-thing”形式的驼峰式单词时,standard 除非是类名,否则不会大写路由单词。所以nonthingnonnull .)

除了运行检查器时,注释实际上也不会强制执行规则。您可以静态包含一个方法来进行检查:

public static <T> T nonnull(T value) 
    if (value == null) 
        throwNPE();
    
    return value;

private static void throwNPE() 
    throw new NullPointerException();

在构造函数中返回值很方便:

import static pkg.Check.nonnull;

class MyClass 
    @Nonnull private final String thing;
    public MyClass(@Nonnull String thing) 
        this.thing = nonnull(thing);
    
    ...

【讨论】:

谢谢汤姆。我认为注释很棒。而且这个实现看起来更干净。【参考方案10】:

是的,公共方法应该清理输入,尤其是在错误的输入可能导致方法代码出现问题的情况下。快速失败是个好主意;即尽快检查。 Java 7 添加了一个新的Objects 类,可以轻松检查空参数并包含自定义消息:

public final void doSomething(String s)

  Objects.requireNonNull(s, "The input String cannot be null");
  // rest of your code goes here...

这将抛出一个NullPointerException

Objects 类的 Javadocs:http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html

【讨论】:

以上是关于我们是不是应该总是在第一行检查java中方法的每个参数是不是为null?的主要内容,如果未能解决你的问题,请参考以下文章

Shell如何检查文件中的一行中是不是存在模式

编码标准:是不是应该总是在每个方法或函数的末尾写“return”? [复制]

检查返回值是不是不为空,如果是,则在一行中使用一个方法调用将其分配

在整个应用程序中检查 android studio 中的互联网连接。 (我们是不是需要在每个 java 活动中编写连接管理器函数?) [重复]

多人游戏是不是应该总是根据每个客户端请求从数据库中请求数据?

我应该在删除之前检查一行是不是存在吗?