断言空检查

ACH*_*CHC 7 java

似乎广泛接受断言语句应保留用于测试和生产中禁用,因为错误应该已经解决,并且启用断言会影响性能.然而,使用if语句进行空检查肯定也是如此.为什么这段代码被认为适合生产

if(x != null) {
    x.setId(idx);
    if (y != null) {
        if (y.id == x.id) {
            x.doSth();
        }
    } else {
        //handle error
    }
} else {
    //handle error
}
Run Code Online (Sandbox Code Playgroud)

但这段代码不是吗?(假设启用了断言)

try {
    assert(x != null); 
    x.setId(idx);
    assert(y != null);
    if (y.id == x.id) {
        x.doSth();
    }
} catch (AssertionError e) {
    //handle error
}
Run Code Online (Sandbox Code Playgroud)

我理解在预期变量可能未初始化时使用if语句.然而,当它用于防御性编码时,断言似乎更优雅和可读.

我还测试了每种方法的性能:

public class AssertTest {

    static final int LOOPS = 10000000;

    public static void main(String[] args) {

            String testStr = "";

            long startNotEqualsTest = System.currentTimeMillis();
            for (int i = 0; i < LOOPS; i++) {
                if (testStr != null) {
                    testStr = System.currentTimeMillis() + "";
                } else {
                    throw new RuntimeException("We're doomed");
                }
            }
            long notEqualsTestDuration = System.currentTimeMillis() - startNotEqualsTest;

            testStr = "";

            long startAssertTest = System.currentTimeMillis();      
            for (int i = 0; i < LOOPS; i++) {
                try {
                    assert(testStr != null);
                    testStr = System.currentTimeMillis() + "";
                } catch (AssertionError e) {
                    throw new RuntimeException("We're doomed");
                }
            }
            long assertTestDuration = System.currentTimeMillis() - startAssertTest;

            System.out.println("Duration with if : " + notEqualsTestDuration + "ms");
            System.out.println("Duration with assert : " + assertTestDuration + "ms");  
    }
}
Run Code Online (Sandbox Code Playgroud)

两种方法的时间安排大致相同:

Duration with if : 1234ms
Duration with assert : 1313ms
Run Code Online (Sandbox Code Playgroud)

禁用断言几乎没有区别:

Duration with if : 1391ms
Duration with assert : 1375ms
Run Code Online (Sandbox Code Playgroud)

我是否错过了任何令人信服的理由,为什么如果条件优于断言,则进行空检查?

Mat*_*att 5

问问自己如何处理null案件?如果一个对象null不应该是你做什么的.在大多数情况下,完全没有处理它.让它NullPointerException在执行后的某个时间产生.无论如何,它很可能是编程错误,因此ExceptionHandler最终可以将其写入日志中.

当然,有些情况下您需要对null对象做出反应.if-else就这种情况而言.这很容易,自我解释,每个程序员都知道构造,所以为什么不使用它.assert无论如何,在生产中是沮丧的.例如,请参阅SO上的这篇文章.而且,根据我的口味,使用try/catch块非常麻烦.

还有其他选择.例如,DavidW建议使用注释,这是完全没问题的,只要您确保解释这些注释(例如,在迁移代码时可能会出现问题).

另一种方法是Validator类.例如,Apache Commons库有一个Validate类,用于检查某些条件,如果条件未满,则会抛出相应的异常.当然,您也可以编写自己的Validators来抛出自定义异常.你最终会得到一个简洁的单行内容

Validate.notNull(myObj) 
Validate.hasEmailCorrectSyntax("foo@bar.com");
Run Code Online (Sandbox Code Playgroud)

另请参阅 Java的Object.requireNotNull