问题:Java中的异常处理实际上是否很慢?
传统观念以及许多谷歌搜索结果表明,不应将特殊逻辑用于Java中的正常程序流程.通常有两个原因,
和
这个问题是关于#1.
例如,这个页面将Java异常处理描述为"非常慢",并将缓慢与异常消息字符串的创建联系起来 - "然后将此字符串用于创建抛出的异常对象.这并不快." Java中的有效异常处理这篇文章说"其原因在于异常处理的对象创建方面,从而使异常本身变得缓慢".另一个原因是堆栈跟踪生成减慢了它的速度.
我的测试(使用Java 1.6.0_07,Java HotSpot 10.0,在32位Linux上)表明异常处理并不比常规代码慢.我尝试在循环中运行一个执行一些代码的方法.在方法结束时,我使用布尔值来指示是返回还是抛出.这样实际处理是一样的.我尝试以不同的顺序运行方法并平均我的测试时间,认为它可能是JVM升温.在我的所有测试中,投掷至少与返回一样快,如果不是更快(最多快3.1%).我对我的测试错误的可能性持开放态度,但我没有看到代码示例,测试比较或过去一两年中显示Java中的异常处理的结果慢.
让我沿着这条路走下去的是我需要使用的API,它将异常作为正常控制逻辑的一部分.我想在他们的使用中纠正它们,但现在我可能无法做到.相反,我是否必须赞美他们的前瞻性思维?
在即时编译中的高效Java异常处理文章中,作者建议单独存在异常处理程序,即使没有抛出异常,也足以阻止JIT编译器正确优化代码,从而减慢它的速度.我还没有测试过这个理论.
我有一个项目,我们经常使用它将Integer.parseInt()
String转换为int.当出现问题时(例如,String
不是数字而是字母a
或其他),此方法将引发异常.但是,如果我必须在我的代码中处理各种异常,那么这很快就会变得非常难看.我想把它放在一个方法中,但是,我不知道如何返回一个干净的值,以表明转换出错了.
在C++中,我可以创建一个接受指向int的指针的方法,让方法本身返回true或false.但是,据我所知,这在Java中是不可能的.我还可以创建一个包含true/false变量和转换值的对象,但这似乎也不理想.对于全局值也是如此,这可能会给我带来一些多线程的麻烦.
那么有一个干净的方法吗?
在我有限的经验中,我参与了几个项目,这些项目有一些字符串实用程序类,其中包含确定给定字符串是否为数字的方法.这个想法一直都是一样的,然而,实施却有所不同.有些使用try/catch包围解析尝试
public boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {}
return false;
}
Run Code Online (Sandbox Code Playgroud)
和其他人匹配正则表达式
public boolean isInteger(String str) {
return str.matches("^-?[0-9]+(\\.[0-9]+)?$");
}
Run Code Online (Sandbox Code Playgroud)
这些方法中的一种比另一种更好吗?我个人更喜欢使用正则表达式方法,因为它很简洁,但是如果在迭代过程中调用,例如,数十万个字符串的列表,它会在par上执行吗?
注意:由于我是网站的新手,我不完全理解这个社区Wiki业务,所以如果这属于那里让我知道,我很乐意移动它.
编辑: 有了所有的TryParse建议,我把Asaph的基准代码(感谢一个很棒的帖子!)移植到C#并添加了一个TryParse方法.而且看起来,TryParse赢得了胜利.然而,尝试捕获方法耗费了大量时间.我认为我做错了什么!我还更新了正则表达式来处理负数和小数点.
更新的C#基准代码的结果:
00:00:51.7390000 for isIntegerParseInt
00:00:03.9110000 for isIntegerRegex
00:00:00.3500000 for isIntegerTryParse
Run Code Online (Sandbox Code Playgroud)
使用:
static bool isIntegerParseInt(string str) {
try {
int.Parse(str);
return true;
} catch (FormatException e){}
return false;
}
static bool isIntegerRegex(string str) {
return Regex.Match(str, "^-?[0-9]+(\\.[0-9]+)?$").Success;
}
static bool isIntegerTryParse(string str) {
int bob;
return Int32.TryParse(str, out bob); …
Run Code Online (Sandbox Code Playgroud) 有一些情况我需要将字符串转换为浮点数或其他一些数值数据类型,但有可能获得一些不可转换的值,如" - "或"/",我无法预先验证所有值以删除他们.我想避免使用try/catch这个问题,还有其他方法在java中进行正确的转换吗?类似于C#的东西TryParse
?
我想检查是否String
传递给Integer.valueOf(String s)
要解析的有效String.如果一个不可解析,我需要返回0.
我是通过以下方式完成的:
try{
Integer.valueOf(String s)
} catch(NumberFormatException e) {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这样做是不好的方法吗?