我有一组Java程序正在获得一些运行时异常。我想知道是否有一个自动机制来识别导致异常的罪魁祸首变量。
例如:
public int multiply(String x, String y){
return Integer.parseInt(x) * Integer.parseInt(y);
}
当你致电multiply("4","ab")
时,那么在运行时,我们会得到一个NumberFormatException
。是否有任何自动化流程来识别变量y
是否导致/导致此异常?
EDIT1:
在收到精彩开发人员的一些建议之后,我认为它无法在代码级别解决,而是我应该在Java编译器中做一些事情。有没有人想过更改可能有助于这种情况的Java编译器?
即使在编译器中不可能,任何人都可以提出有关JVM中的更改的建议吗?
答案 0 :(得分:2)
更新
我认为它无法在代码级别解决,而是我应该在Java编译器中做一些事情。
根据定义,编译器无法检测到RuntimeException
,只能在程序执行时捕获和处理它们。这可以仅在代码级别"解决
即使在编译器中不可能,任何人都可以提出有关JVM中的更改的建议吗?
尽管我尽了最大的努力,你仍坚持沿着这条道路前进,所以我将尝试解释你将要做的事情。但是要明白a)这是非常复杂的,并且b)几乎肯定不是正确的解决方案。 修复您的代码,而不是JVM 。
您基本上需要重新设计Java bytecode以包含所需的其他上下文,并更改compile the JDK from source。这在理论上是可行的,因为Java是开源的,但它将是一项英勇的事业。没有"给我更多信息"标志你可以开箱即用JVM;这是JVM Options的列表。
真正的答案从这里开始:
这取决于你的意思"自动化"。据我所知,没有办法检查异常以确定哪个变量导致错误(我希望它对NPE来说是真的,会非常有帮助)。但是您可以改进代码以使其更加清晰。
使用调试程序逐步执行程序
在我们进入自动化之前,一个选项是use the Java debugger逐行逐步执行代码并确切地查看故障发生的位置。这是一个高度手动的过程,但可以帮助您难以理解故障。
将特殊电话拆分为单独的行
堆栈跟踪确实提供了相关的行号,因此如果您将方法更改为:
public int multiply(String x, String y){
int intX = Integer.parseInt(x);
int intY = Integer.parseInt(y);
return intX * intY;
}
然后NumberFormatException
现在将出现在此函数的第一行或第二行,让您看到导致错误的行。
使用更多上下文提升包装器异常
行号并不是最有用的信息,我们可以通过提高自己的例外来做得更好:
private int parseIntMsg(String num, String desc)
throws IllegalArgumentException {
try {
return Integer.parseInt(num);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
"Failed to parse "+desc+"; was '"+num+"'", e);
}
}
public int multiply(String x, String y) {
return parseIntMsg(x, "x") * parseIntMsg(y, "y");
}
现在,这会使IllegalArgumentException
消息更加清晰Failed to parse x; was 'ab'
。
在调用此方法之前进行完整性检查
这里真正发生的事情是你没有在合适的时间处理这个错误案例。相反,尽早进行理智检查,并明确处理它们。您是否正在从用户读取字符串?明确检查一下号码,然后将其交还给用户,如果不是,请更正,而不是等到你的代码的肚子里然后绕过可能会或可能不会的字符串。是有效的整数。实际上,您应该对您已定义的multiply(String, String)
方法毫无用处。相反,将输入显式解析为您要使用的类型,然后在验证解析成功后显式处理它们。有关此主题的更多想法,请参阅Why is it good to split a program into multiple classes?。
还要考虑使用优秀的Guava库中的Preconditions
;这些实用程序方法允许您添加大量丰富的错误消息,并期望您的代码失败时会发生什么。
答案 1 :(得分:0)
我认为你需要一些可以在异常后打印输入参数的拦截器。例如,您可以在这种情况下使用AspectJ。以下是如何执行此操作的示例AspectJ-catch-handle-exception。
答案 2 :(得分:0)
对于您的示例,您可以做的是:
public int multiply(String x, String y){
if (!x.matches("(\d+|\d*\.\d+)")) {
// give out that x is not a number
} else if (!y..matches("(\d+|\d*\.\d+)")) {
// give out thaqt y is not a number
} else {
return Integer.parseInt(x) * Integer.parseInt(y);
}
}
与异常相关的最好的事情是控制它们何时发生。即使您使用的函数抛出异常,也要确保是您的代码决定是否报告此异常。
可能存在异常可接受的情况,您可以在日志中提及它并让代码继续,或者您停止流程并提及您为什么这样做,以免导致对可怜的毫无疑问的用户造成混淆。