#锤爆leader狗头!什么?try-catch一定要放在循环体外?

157 阅读2分钟

try-catch怎么能放在循环内部呢?这样多影响性能啊?你会不会写代码?

去nmd吧,下面就让你看看try-catch对性能的影响,把你狗头锤烂!!!

耗时测试

先说结论,当无异常发生时,循环内外加try-catch效率相差无几;如果循环内部异常抛出过多,则会显著降低执行效率。

代码

循环体外try-catch

    public static Long outLoop(){
        int n = 0;
        Long startTime =  System.currentTimeMillis();
        try{
            for (int i = 0; i < loopTime; i++) {
                ++n;
            }
        }catch (Exception e){
        }
        Long endTime = System.currentTimeMillis();
        return endTime-startTime;
    }

循环体内try-catch

抛异常

    public static Long innerThrowLoop(){
        int n = 0;
        Long startTime =  System.currentTimeMillis();
        for (int i = 0; i < loopTime; i++) {
            try {
                ++n;
                if(n == 1){
                    throw new Exception("");
                }
            }catch (Exception e){
            }
        }
        Long endTime = System.currentTimeMillis();
        return endTime-startTime;
    }

无异常

    public static Long innerLoop(){
        int n = 0;
        Long startTime =  System.currentTimeMillis();
        for (int i = 0; i < loopTime; i++) {
            try {
                ++n;
            }catch (Exception e){
            }
        }
        Long endTime = System.currentTimeMillis();
        return endTime-startTime;
    }

耗时

采用循环1亿次进行耗时测试:

底层原理

从字节码角度分析为什么循环内外try-catch在不发生异常时效率一样。

代码

package exception;

public class TryCatchSimpleDemo {
    public static void main(String[] args) {
        try{
            System.out.println("hello world");
        }catch (Exception e){
        }
    }
}

命令

javac TryCatchSimpleDemo.java
javap -c TryCatchSimpleDemo.class > code.txt

字节码分析

Compiled from "TryCatchSimpleDemo.java"
public class exception.TryCatchSimpleDemo {
  public exception.TryCatchSimpleDemo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String hello world
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: goto          12
      11: astore_1
      12: return
    Exception table:
       from    to  target type
           0     8    11   Class java/lang/Exception
}

异常表

在字节码尾部可以看到如下异常表,记录try-catch起止的行数和异常类型。

  • from:起始行数
  • to:终止行数
  • target:异常处理开始位置
  • type:异常类型
   Exception table:
       from    to  target type
           0     8    11   Class java/lang/Exception

从字节码指令可以看出,当代码运行时出错时,会先判断出错数据是否在 from 到 to 的范围内,如果是则从 target 标志位往下执行,如果没有出错,直接 goto 到 return。也就是说,如果代码不出错的话,性能几乎是不受影响的,和正常的代码的执行逻辑是一样的

总结

try-catch无论放在循环内外,在不发生异常时对效率的影响微乎其微,由于try-catch内部的指令不能进行重排序,因此会造成一些影响但是不大。

在业务开发中主要还是考虑业务场景在决定是否要在循环内部使用try-catch。下次leader说不行,直接怼回去!

参考文献

[1] blog.csdn.net/b644ROfP20z…