抛出并捕获异常,还是使用实例?

我在变量中有一个异常(未抛出)。

什么是最好的选择?

Exception exception = someObj.getExcp();
try {
    throw exception;
} catch (ExceptionExample1 e) {
    e.getSomeCustomViolations();
} catch (ExceptionExample2 e) {
    e.getSomeOtherCustomViolations(); 
}

Exception exception = someObj.getExcp();
if (exception instanceof ExceptionExample1) {
    exception.getSomeCustomViolations();
} else if (exception instanceof ExceptionExample2) {
    exception.getSomeOtherCustomViolations();
}

答案 1

我建议使用,因为它可能会更快。引发异常是一项复杂且成本高昂的操作。JVM 经过优化,可在发生异常的情况下快速运行。例外情况应该是例外情况。instanceof

请注意,该技术可能不会按所示进行编译,如果您的异常类型是已检查的异常,编译器将抱怨您必须捕获该类型或将其声明为抛出(如果您使用该技术,则对应于子句),这可能有帮助,也可能没有帮助,具体取决于您希望如何处理不属于特定子类型之一的异常。throwelse { ... }instanceof


答案 2

讨厌打破每个人的泡沫,但使用速度更快。这并不是说这是“正确”的方式,但如果性能是关键,那么这就是赢家。以下是以下程序的结果:try/catch

运行 1

  • 子运行 1:实例:130 毫秒
  • 子运行 1:尝试/捕获:118 毫秒
  • 子运行 2:实例:96 毫秒
  • 子运行 2:尝试/捕获:93 毫秒
  • 子运行 3:实例:100 毫秒
  • 子运行 3:尝试/捕获:99 毫秒

运行 2

  • 子运行 1:实例:140 毫秒
  • 子运行 1:尝试/捕获:111 毫秒
  • 子运行 2:实例:92 毫秒
  • 子运行 2:尝试/捕获:92 毫秒
  • 子运行 3:实例:105 毫秒
  • 子运行 3:尝试/捕获:95 毫秒

运行 3

  • 子运行 1:实例:140 毫秒
  • 子运行 1:尝试/捕获:135 毫秒
  • 子运行 2:实例:107 毫秒
  • 子运行 2:尝试/捕获:88 毫秒
  • 子运行 3:实例:96 毫秒
  • 子运行 3:尝试/捕获:90 毫秒

测试环境

  • 爪哇: 1.7.0_45
  • Mac OSX Mavericks

对每次运行的预热子运行进行折扣,该方法最多只能实现 的性能。该方法的平均(折扣预热)为 98 毫秒,平均值为 92 毫秒。instanceoftry/catchinstanceoftry/catch

请注意,我没有改变每种方法的测试顺序。我总是测试一个块,然后是一个块。我很想看到其他结果与这些发现相矛盾或证实。instanceoftry/catch

public class test {

    public static void main (String [] args) throws Exception {
        long start = 0L;
        int who_cares = 0; // Used to prevent compiler optimization
        int tests = 100000;

        for ( int i = 0; i < 3; ++i ) {
            System.out.println("Testing instanceof");
            start = System.currentTimeMillis();
            testInstanceOf(who_cares, tests);
            System.out.println("instanceof completed in "+(System.currentTimeMillis()-start)+" ms "+who_cares);

            System.out.println("Testing try/catch");
            start = System.currentTimeMillis();
            testTryCatch(who_cares, tests);
            System.out.println("try/catch completed in "+(System.currentTimeMillis()-start)+" ms"+who_cares);
        }
    }

    private static int testInstanceOf(int who_cares, int tests) {
        for ( int i = 0; i < tests; ++i ) {
            Exception ex = (new Tester()).getException();
            if ( ex instanceof Ex1 ) {
                who_cares = 1;
            } else if ( ex instanceof Ex2 ) {
                who_cares = 2;
            }
        }
        return who_cares;
    }

    private static int testTryCatch(int who_cares, int tests) {
        for ( int i = 0; i < tests; ++i ) {
            Exception ex = (new Tester()).getException();
            try {
                throw ex;
            } catch ( Ex1 ex1 ) {
                who_cares = 1;
            } catch ( Ex2 ex2 ) {
                who_cares = 2;
            } catch ( Exception e ) {}
        }
        return who_cares;
    }

    private static class Ex1 extends Exception {}

    private static class Ex2 extends Exception {}

    private static java.util.Random rand = new java.util.Random();

    private static class Tester {
        private Exception ex;
        public Tester() {
            if ( rand.nextBoolean() ) {
                ex = new Ex1();
            } else {
                ex = new Ex2();
            }
        }
        public Exception getException() {
            return ex;
        }
    }
}

推荐