2011-03-02 25 views
21

每种方法都接受一组参数值。我们是否应始终验证输入参数的非空值,还是允许代码通过经典RunTimeException失败?我们是否应该总是在第一行中检查java中的方法的每个参数为null?

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

void public(String a, Integer b, Object c) 
{ 
    if(a == null || b == null || c == null) 
    { 
    throw new RunTimeException("Message..."); 
    } 
    .....business logic..... 
} 
+0

的[?在哪里检查对象为空或不是]可能重复(http://stackoverflow.com/questions/706263/where-to-check-if -an-object-is-null-or-not) – NPE 2011-03-02 20:23:04

+0

另一个问题是关于'.net',但实质上是完全相同的。 – NPE 2011-03-02 20:24:04

+0

目前的答案都没有提到使用注释和静态分析,例如FindBugs @NonNull,@CheckForNull等。另外,虽然这不是上面提到的.Net问题的重复,但它可能至少在stackoverflow中覆盖过一次。 – 2011-03-02 20:48:39

回答

22

最好的办法是只在必要时检查。例如,如果你的方法是private,所以你知道没有其他人使用它,并且你知道你没有传入任何空值,那么没有必要再检查一次。

如果你的方法是public虽然,谁知道你的API的用户将尝试做什么,所以更好地检查。

如果有疑问,请检查

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

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

即使你检查null,合理的选择是抛出一个NullPointerException,这str.length()会为你闲着。

+28

我不会建议依靠自动NullPointerException来取代显式参数验证。原因有二:(a)验证应该尽可能早地发生(想法在遇到NPE之前改变某些状态)和(b)代码可支持性。类X中的NPE将首先转到类X的所有者,因为它看起来像是实现中的错误。但是,如果你显式检查args为null,并且抛出IllegalArgumentException异常(也是类似NPE的RuntimeException),那么显然问题在于类X的调用者。 – 2011-03-02 21:00:07

1

我没有看到这么做的很多观点。您只是简单地复制您在第一次尝试在abc上运行时免费获得的行为。

0

这取决于你的代码试图做什么以及你想抛出一个Exception的情况。有时你会希望你的方法总是抛出一个异常,如果你的方法将无法正确使用空值。如果你的方法可以解决空值,那么可能不需要抛出异常。

添加太多检查异常可能会导致非常复杂和复杂的代码。这是他们没有被包含在C#中的原因。

1

不可以。假定参数不为空并且否则将抛出NullPointerException的标准。如果你的方法允许一个参数为null,你应该在你的api中声明。

1

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

如果不是,它是很好的做法,以检查null并抛出一个异常,否则你会得到一个NullPointerException,你应该永远也追不上,因为它的出现总是表示您忘了检查你的变量在你的代码。 (如果你抓住它,你可能会错过其他被抛出的事件,并且你可能会引入错误)。另一方面,如果抛出RunTimeException或其他一些自定义异常,则可以在上游的某个位置处理它,以便更好地控制所发生的事情。

0

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

我的喜好,按顺序将是:

  1. 理智做事与空。明智的做法完全取决于情况,但抛出自定义异常不应该是您的首选。
  2. 使用一个断言来检查null并彻底测试,消除了由于--a.k.a错误而产生空输入的任何情况。
  3. 对于公共API,不允许使用null的文档,并让它在NPE中失败。
+0

@downvoter没有解释?只是不喜欢我的臂架的切割? – 2011-03-03 00:29:19

1

你不应该抛出一个运行时异常,除非它是一个真正的系统的操作,如丢失了关键的运行参数,一个致命的条件,但即使如此,这是有问题的系统应该只是无法启动。

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

在任何情况下,在尝试操作它们之前检查传入的任何参数的空值总是一个好习惯,所以当有人向您传递错误数据时,您不会得到NullPointerExceptions

-5

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

JDK源,和Joshua Bloch的书,是可怕学习的榜样,因为他们的目标是非常不同的受众。我们有多少人正在为数百万程序员编写公共API?

2

这是Java的一个不幸的方面是引用可null并没有办法,因为它们不是语言来指定。

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

JSR305(现已失效)允许您注释参数声明,他们不应该给予null秒。

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

冗长,但是这是Java的为您服务。还有其他的注释库和检查器的功能差不多,但都不是标准的。

(备注大写:当窗体“非物”的骆驼外壳也就是说,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); 
    } 
    ... 
+0

谢谢汤姆。我认为注释很棒。而且这个实现看起来更干净。 – 2011-03-13 18:54:11

1

是的,公共的方法应该擦洗输入,特别是如果错误的输入可能导致内部问题你的方法的代码。快速失败是个好主意;也就是说,尽快检查。 Java 7中添加了一个新Objects类,可以很容易地检查null参数,包括自定义消息:

public final void doSomething(String s) 
{ 
    Objects.requireNonNull(s, "The input String cannot be null"); 
    // rest of your code goes here... 
} 

这将引发NullPointerException

Javadoc文档Objects类:http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html

相关问题