取决于异常的实现方式。最简单的方法是使用setjmp和longjmp。这意味着将CPU的所有寄存器都写入堆栈(这已经花费了一些时间),并且可能需要创建一些其他数据…所有这些都已经在try语句中发生。throw语句需要展开堆栈并恢复所有寄存器的值(以及VM中可能的其他值)。因此try和throw都同样缓慢,而且也相当慢,但是,如果没有抛出异常,则在大多数情况下退出try块几乎不会花费任何时间(因为所有内容都放在堆栈中,如果该方法存在,则堆栈会自动清除)。
Sun和其他公司认识到,这可能不是最佳选择,并且随着时间的流逝,虚拟机当然会越来越快。还有另一种实现异常的方法,它可以使尝试本身快如闪电(实际上一般而言,尝试都不会发生任何事情-当类由VM加载时,所有需要发生的事情都已经完成了),并且抛出异常的速度也不太慢。我不知道哪个JVM使用这种更好的新技术…
…但是你是否使用Java编写,因此以后的代码只能在一个特定系统上的一个JVM上运行?由于它是否可以在任何其他平台或任何其他JVM版本(可能是任何其他供应商的版本)上运行,谁说他们也使用快速实现?快速的比慢的更复杂,并且在所有系统上都不容易实现。你想保持便携性吗?然后,不要依赖快速的异常。
在try块中执行的操作也有很大的不同。如果你打开一个try块,并且从不从该try块中调用任何方法,则try块将非常快,因为JIT实际上可以像简单的goto一样处理throw。如果抛出异常(它只需要跳转到catch处理程序),它既不需要保存堆栈状态,也不需要取消堆栈。但是,这不是你通常执行的操作。通常,你打开一个try块,然后调用一个可能引发异常的方法,对吗?即使你仅在方法中使用try块,这将是哪种方法,而不会调用任何其他方法?它会只计算一个数字吗?那你需要例外吗?有许多更优雅的方法来调节程序流。除了简单的数学运算外,
请参阅以下测试代码:
public class Test { int value; public int getValue() { return value; } public void reset() { value = 0; } // Calculates without exception public void method1(int i) { value = ((value + i) / i) << 1; // Will never be true if ((i & 0xFFFFFFF) == 1000000000) { System.out.println("You'll never see this!"); } } // Could in theory throw one, but never will public void method2(int i) throws Exception { value = ((value + i) / i) << 1; // Will never be true if ((i & 0xFFFFFFF) == 1000000000) { throw new Exception(); } } // This one will regularly throw one public void method3(int i) throws Exception { value = ((value + i) / i) << 1; // i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both // an AND operation between two integers. The size of the number plays // no role. AND on 32 BIT always ANDs all 32 bits if ((i & 0x1) == 1) { throw new Exception(); } } public static void main(String[] args) { int i; long l; Test t = new Test(); l = System.currentTimeMillis(); t.reset(); for (i = 1; i < 100000000; i++) { t.method1(i); } l = System.currentTimeMillis() - l; System.out.println( "method1 took " + l + " ms, result was " + t.getValue() ); l = System.currentTimeMillis(); t.reset(); for (i = 1; i < 100000000; i++) { try { t.method2(i); } catch (Exception e) { System.out.println("You'll never see this!"); } } l = System.currentTimeMillis() - l; System.out.println( "method2 took " + l + " ms, result was " + t.getValue() ); l = System.currentTimeMillis(); t.reset(); for (i = 1; i < 100000000; i++) { try { t.method3(i); } catch (Exception e) { // Do nothing here, as we will get here } } l = System.currentTimeMillis() - l; System.out.println( "method3 took " + l + " ms, result was " + t.getValue() ); }}结果:
method1 took 972 ms, result was 2method2 took 1003 ms, result was 2
method3 took 66716 ms, result was 2
try块的速度太慢,无法排除诸如后台进程之类的混淆因素。但是捕获块杀死了所有东西并使它变慢了66倍!
就像我说的,如果将try / catch放在同一方法(method3)中并全部抛出,结果将不会那么糟,但这是我不依赖的特殊JIT优化。即使使用此优化,抛出也仍然很慢。所以我不知道你要在这里做什么,但是绝对有比使用try / catch / throw更好的方法。



