Java 抛出并捕获异常,还是使用 instanceof?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20431614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:52:39  来源:igfitidea点击:

Throw and catch an exception, or use instanceof?

javaperformanceexceptioninstanceofthrows

提问by Ruslan

I have an exception in a variable (not thrown).

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

What's the best option?

最好的选择是什么?

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

or

或者

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

采纳答案by Boann

I'd advise using instanceofas it will likely be faster. Throwing an exception is a complicated and expensive operation. JVMs are optimized to be fast in the case when exceptions don'thappen. Exceptions should be exceptional.

我建议使用,instanceof因为它可能会更快。抛出异常是一项复杂而昂贵的操作。JVM 被优化为在发生异常的情况下速度更快。例外应该是例外。

Note that the throwtechnique probably won't compile as shown, if your exception type is a checked exception, the compiler will complain that you must catch that type or declare it as thrown (corresponding to an else { ... }clause if you use the instanceoftechnique), which might or might not be helpful, depending on how you want to handle exceptions that are not one of the specific sub-types.

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

回答by Joe

You could also use polymorphism by creating an interface for your custom exceptions that contains the getCustomViolation() method. Then each Custom exception would implement that interface and that method.

您还可以通过为包含 getCustomViolation() 方法的自定义异常创建接口来使用多态性。然后每个自定义异常将实现该接口和该方法。

回答by Elliott Frisch

I strongly urge you to actually use a plain object to represent your "constraint". Whether a marking interface (e.g. Message) or a java.lang.Stringis up to you. Exceptions are not meant to be used as you intend, even if either could be made to work (I would expect the second to be faster, but a premature optimization...).

我强烈建议您实际使用一个普通对象来表示您的“约束”。是标记接口(例如Message)还是 ajava.lang.String取决于您。例外并不意味着按照您的意图使用,即使可以使任何一个工作(我希望第二个更快,但过早优化......)。

回答by disrvptor

Hate to burst everyone's bubble, but using try/catchis faster. That's not to say it is the "correct" way, but if performance is key then that's the winner. Here are the results from the following program:

讨厌爆所有人的泡沫,但使用try/catch。这并不是说这是“正确”的方式,但如果性能是关键,那就是赢家。以下是以下程序的结果:

Run 1

运行 1

  • Sub-run 1: Instanceof : 130 ms
  • Sub-run 1: Try/catch : 118 ms
  • Sub-run 2: Instanceof : 96 ms
  • Sub-run 2: Try/catch : 93 ms
  • Sub-run 3: Instanceof : 100 ms
  • Sub-run 3: Try/catch : 99 ms
  • 子运行 1:Instanceof:130 毫秒
  • 子运行 1:尝试/捕获:118 毫秒
  • 子运行 2:Instanceof:96 毫秒
  • 子运行 2:尝试/捕获:93 毫秒
  • 子运行 3:Instanceof:100 毫秒
  • 子运行 3:尝试/捕获:99 毫秒

Run 2

运行 2

  • Sub-run 1: Instanceof : 140 ms
  • Sub-run 1: Try/catch : 111 ms
  • Sub-run 2: Instanceof : 92 ms
  • Sub-run 2: Try/catch : 92 ms
  • Sub-run 3: Instanceof : 105 ms
  • Sub-run 3: Try/catch : 95 ms
  • 子运行 1:Instanceof:140 毫秒
  • 子运行 1:尝试/捕获:111 毫秒
  • 子运行 2:Instanceof:92 毫秒
  • 子运行 2:尝试/捕获:92 毫秒
  • 子运行 3:Instanceof:105 毫秒
  • 子运行 3:尝试/捕获:95 毫秒

Run 3

运行 3

  • Sub-run 1: Instanceof : 140 ms
  • Sub-run 1: Try/catch : 135 ms
  • Sub-run 2: Instanceof : 107 ms
  • Sub-run 2: Try/catch : 88 ms
  • Sub-run 3: Instanceof : 96 ms
  • Sub-run 3: Try/catch : 90 ms
  • 子运行 1:Instanceof:140 毫秒
  • 子运行 1:尝试/捕获:135 毫秒
  • 子运行 2:Instanceof:107 毫秒
  • 子运行 2:尝试/捕获:88 毫秒
  • 子运行 3:Instanceof:96 毫秒
  • 子运行 3:尝试/捕获:90 毫秒

Test environment

测试环境

  • Java: 1.7.0_45
  • Mac OSX Mavericks
  • Java:1.7.0_45
  • Mac OSX 小牛队

Discounting warmup sub-runs of each run the instanceofmethod only achieves at best the performance of try/catch. The average (discounting warm-ups) of the instanceofmethod is 98 ms and the average of try/catchis 92 ms.

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

Please note I did not vary the order in which each method was tested. I always tested a block of instanceofthen a block of try/catch. I would love to see other results contradicting or confirming these findings.

请注意,我没有改变测试每种方法的顺序。我总是测试一个块instanceof然后一个块try/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;
        }
    }
}