Nic*_*ner 10 java exception control-flow
我听说使用控制流异常是不好的做法.你觉得这怎么样?
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
}
Run Code Online (Sandbox Code Playgroud)
因此,如果未找到匹配项,则整数将为-1.当我尝试获取子字符串时,这将导致异常g0.substring(0, -1).然后该函数返回一个对象,表明找不到匹配项.
这是不好的做法吗?我可以手动检查每个索引以查看它们是否全部为-1,但这感觉更像是工作.
UPDATE
我删除了try-catch块并将其替换为:
if (g0Left == -1 || g0Right == -1 || g1Left == -1 || g1Right == -1) {
return new StringMatch();
}
Run Code Online (Sandbox Code Playgroud)
哪个更好:检查每个变量是否为-1,或者使用布尔值foundMatch来跟踪并在最后检查它?
Yan*_*ton 17
通常例外是昂贵的操作,正如名称所暗示的那样,特殊条件.因此,在控制应用程序流程的上下文中使用它们确实被认为是不好的做法.
特别是在您提供的示例中,您需要对您为StringMatch构造函数提供的输入进行一些基本验证.如果它是一个返回错误代码的方法,以防一些基本参数验证失败,你可以避免事先检查,但事实并非如此.
是的,这是一种不好的做法,特别是当你有办法避免异常时(在尝试索引之前检查字符串长度).Try和catch块旨在将"普通"逻辑与"异常"和错误逻辑分开.在您的示例中,您已将"正常"逻辑扩展到异常/错误块中(未找到匹配也不例外).您也在滥用,substring因此您可以利用它产生的错误作为控制流.
小智 6
程序流程应尽可能直线(因为即使应用程序变得相当复杂),也要使用标准控制流程结构.接触代码的下一个开发人员可能不是您,并且(正确地)误解了您使用异常而非条件来确定控制流的非标准方式.
在一些遗留代码重构期间,我现在正在针对这个问题稍微倾斜一点.
我用这种方法发现的最大问题是使用try/catch打破了正常的程序流程.
在我正在处理的应用程序中(这与您应用的示例不同),异常用于在方法调用内进行通信,发生给定结果(例如查找帐号但未找到它).这会在客户端创建意大利面条代码,因为调用方法(在非异常事件或正常用例事件期间)会突破它在调用之前执行的任何代码以及catch块.这在一些非常长的方法中重复了很多次,使代码很容易被误读.
对于我的情况,一个方法应该返回每个签名的值,除了真正特殊的事件.异常处理机制旨在发生异常时采用另一个路径(尝试从方法中恢复,以便仍然可以正常返回).
在我看来,如果你非常紧密地调整try/catch块的范围,你就可以做到这一点; 但我认为这是一个坏习惯,并且可能导致代码很容易被误解,因为调用代码会将任何抛出的异常解释为'GOTO'类型的消息,从而改变程序流程.我担心虽然这种情况不属于这个陷阱,但这样做往往会导致编码习惯导致我现在生活的噩梦.
那场噩梦并不令人愉快.