Java:异常作为控制流?

2022-09-04 05:38:37

我听说对控制流使用异常是不行的。对此,你怎么看?

public static findStringMatch(g0, g1) {

    int g0Left = -1;
    int g0Right = -1;
    int g1Left = -1;
    int g1Right = -1;

//if a match is found, set the above ints to the proper indices
//...
//if not, the ints remain -1

        try {
            String gL0 = g0.substring(0, g0Left);
            String gL1 = g1.substring(0, g1Left);

            String g0match = g0.substring(g0Left, g0Right);
            String g1match = g1.substring(g1Left, g1Right);

            String gR0 = g0.substring(g0Right);
            String gR1 = g1.substring(g1Right);

            return new StringMatch(gL0, gR0, g0match, g1match, gL1, gR1);
        }
        catch (StringIndexOutOfBoundsException e) {
            return new StringMatch(); //no match found
        }

因此,如果未找到匹配项,则 ints 将为 -1。当我尝试采用子字符串时,这将导致异常。然后,该函数只返回一个对象,指示未找到匹配项。g0.substring(0, -1)

这是不好的做法吗?我可以手动检查每个索引,看看它们是否都是-1,但这感觉需要做更多的工作。

更新

我已经删除了 try-catch 块,并将其替换为以下内容:

    if (g0Left == -1 || g0Right == -1 || g1Left == -1 || g1Right == -1) {
        return new StringMatch();
    }

哪个更好:检查每个变量是否为-1,或者使用布尔值进行跟踪并在最后检查?foundMatch


答案 1

通常,例外情况是代价高昂的操作,顾名思义,例外情况。因此,在控制应用程序流的上下文中使用它们确实被认为是不好的做法。

具体来说,在您提供的示例中,您需要对提供给 StringMatch 构造函数的输入进行一些基本验证。如果它是一个返回错误代码的方法,以防某些基本参数验证失败,则可以避免事先检查,但事实并非如此。


答案 2

我对此做了一些测试。在现代 JVM 上,它实际上对运行时性能的影响不大(如果有的话)。如果在打开调试的情况下运行,则它确实会大大降低速度。

有关详细信息,请参阅以下内容

(我还应该提到,即使不会影响性能,我仍然认为这是一种不好的做法。最重要的是,它反映了一个可能很差的算法设计,很难测试)