Java 要捕获哪个断言错误

Java which assertion error to catch

我自己练习了一些 Java SE 7,遇到了以下问题。我写了一个 public static void 函数 ValidDate,它接受三个字符串,并且只在日期无效时抛出断言错误。 ValidDate 使用两个字符串数组(MONTHSDAYS)作为库来验证给定的日期。 ValidDate 在每个断言测试结束时也有一个唯一的断言表达式:

public static void ValidDate(String month, String day, String year){
    boolean validday = false;
    boolean validmonth = false;
    boolean validyear = true;

    try{
        Integer.parseInt(year);
    }catch(NumberFormatException e){
        validyear = false;
    }
    assert(validyear): "Error: year entry not written in integers.";


    for(String m:MONTHS){
        if(m.equals(month)){
            validmonth = true;
        }
    }
    assert (validmonth): "Error: month entry is not valid; must be an"
            + " integer between (0)1 and 12.";

    ...
}

我的目的是添加 ValidDate 作为 DOB setter (SetDOB ) 我的 public class 。当在 setter 和 中输入无效的 DOB 时,实现将 ValidDate 抛出异常然后 SetDOB 将输出一条消息,表明输入的 DOB 是不可接受的,并且不会更改当前的 DOB 值:

public void SetDOB(String newDOB){
    String[] dates = newDOB.split("/");
    boolean validdate = true;
    if(dates.length == 3){
        try{
            ValidDate(dates[0],dates[1],dates[2]);
        }
        catch(AssertionError e){
            System.out.println("Error: ValidDate threw an assert error.");
            validdate = false;
        }
        if(validdate){
            DOB = newDOB;
        }
    }
    else{
        System.out.println("Please enter a valid DOB of the form: Month/Day"
                + "/Year using integers.");
    }
}

当我尝试 运行 SetDOBDOB,然而,ValidDate 不会为 SetDOB 抛出 AssertionError 来捕获。也没有输出错误信息。我怀疑造成这种情况的原因与我在 ValidDateSetDOB 中使用 try-catch 语句有关。但是,我也可能在没有意识到的情况下犯了一个不同的错误。我希望有人解释我做错了什么以及如何正确完成我的预期任务。如果其他人已经回答了这个或类似的问题,那么请在他们的 post 中添加一个 link。如果我在遇到 linked post.

时发现它多余,我也可能会删除它 post

断言用于测试您的代码假定的不变量。如果断言失败,那应该表明你的代码是错误的,而不是遇到了某种可预测的失败模式。断言不适合后者,因为是否在运行时评估断言完全取决于 VM 参数。

由此可见,抓AssertionError很少是合适的。 (事实上​​ ,捕获任何 Error 很少是合适的。)只有在相当特殊的条件下,才有可能从程序本身的错误中恢复过来。

在您的特定情况下,您的代码可能 运行 没有启用断言。你没有抓住 AssertionError 因为 none 曾经被抛出。

然而,真正的问题是你误解了断言的目的。它们不是表示在执行程序的过程中出现问题,而是表示您对代码的假设是错误的。

当你这样写的时候

assert someValue != null : "some value should be set"

这意味着您编写代码的方式 someValue 以一种或另一种方式设置,并且当代码达到 assert 时,它 必须 已设置。如果有人修改您的代码,使其可以在不设置 someValue 的情况下到达 assert,断言将捕获它。

另一方面,您的代码尝试使用断言进行验证。这就是 exceptions 的用途:

if (!validmonth) {
    throw new InvalidMonthException("Error: month entry is not valid; must be an integer between (0)1 and 12.");
}

注意: 您的代码未捕获断言的最可能原因是您 have not enabled them.

创建您自己的异常 class 而不是 throwing/catching AssertionError。 不要在您的 SetDOB 方法中捕获此异常,而是向 setDOB 方法添加一个 throws 子句。调用 setDOB 方法时捕获异常。