Which is faster, try catch or if-else in java (WRT performance)

前端 未结 12 1928
暖寄归人
暖寄归人 2020-12-05 02:22

Which one is faster:

Either this

try {
  n.foo();
} 
catch(NullPointerException ex) {
}

or

if (n != null) n.foo();         


        
相关标签:
12条回答
  • 2020-12-05 02:37

    The answer to this is not as simple as it looks, because this will depend on the percentage of times that the object is really null. When this is very uncommon (say in 0.1% of the time), it might even be faster. To test this I've done some benchmarking with the following results (with Java 1.6 client):

    Benchmaring with factor 1.0E-4
    Average time of NullIfTest: 0.44 seconds
    Average time of NullExceptionTest: 0.45 seconds
    Benchmaring with factor 0.0010
    Average time of NullIfTest: 0.44 seconds
    Average time of NullExceptionTest: 0.46 seconds
    Benchmaring with factor 0.01
    Average time of NullIfTest: 0.42 seconds
    Average time of NullExceptionTest: 0.52 seconds
    Benchmaring with factor 0.1
    Average time of NullIfTest: 0.41 seconds
    Average time of NullExceptionTest: 1.30 seconds
    Benchmaring with factor 0.9
    Average time of NullIfTest: 0.07 seconds
    Average time of NullExceptionTest: 7.48 seconds
    

    This seems pretty conclusive to me. NPE's are just very slow. (I can post the benchmarking code if wanted)

    edit: I've just made an interesting discovery: when benchmarking using the server JVM, the results change drastically:

    Benchmaring with factor 1.0E-4
    Average time of NullIfTest: 0.33 seconds
    Average time of NullExceptionTest: 0.33 seconds
    Benchmaring with factor 0.0010
    Average time of NullIfTest: 0.32 seconds
    Average time of NullExceptionTest: 0.33 seconds
    Benchmaring with factor 0.01
    Average time of NullIfTest: 0.31 seconds
    Average time of NullExceptionTest: 0.32 seconds
    Benchmaring with factor 0.1
    Average time of NullIfTest: 0.28 seconds
    Average time of NullExceptionTest: 0.30 seconds
    Benchmaring with factor 0.9
    Average time of NullIfTest: 0.05 seconds
    Average time of NullExceptionTest: 0.04 seconds
    

    Using the server VM, the difference is hardly noticable. Still: I'd rather not use catching NullPointerException unless it really is an exception.

    0 讨论(0)
  • Explicitly testing for a null pointer is much faster than using exception handling.

    For the record, most of the oherheads in using exceptions are incurred in the instantiation of the exception object. In particular in the call to fillInStackTrace() which has to:

    • examine every stack frame for the current thread's stack, and
    • create a data structure to capture the stack frame details.

    In some cases, you can reduce this by reusing the exception object, or by overriding an application specific exception's fillInStackTrace() method to make it a no-op. The downside in both cases is that proper stacktraces will no longer be available to help you debug unexpected exceptions. (And neither of these are applicable to the OP's example.)

    While exception instantiation is expensive, exception throwing, propagation and catching are not exactly cheap either.


    There is a second reason why explicit null testing is a better idea. Consider this:

    try {
        doSomething(a.field);
    } catch (NullPointerException ex) {
        System.err.println("a.field is null");
    }
    

    What happens if an NPE happens within the call to doSomething(...) instead of during the evaluation of the a.field expression? Sure, we'll catch an NPE, but we will misdiagnose it, and then attempt to continue ... incorrectly assuming that a.field is unset or something.

    Distinguishing an "expected" NPE from an "unexpected" NPE is theoretically possible, but in practice very difficult. A much simpler and more robust approach is to explicitly test for the null values that you are expecting (e.g. with an if statement), and treat all NPEs as bugs.

    (I'm sure that this is what @Mitch means by "treating exceptions as exceptional", but I think it helps to spell things out with an illustrative example ...)

    0 讨论(0)
  • 2020-12-05 02:42

    If n.foo() happens to throw internally a NPE, you are off for a long debugging session (or worse, your app fails in production..). Just don't do it.

    How many nano-seconds do you plan to save, anyways?

    0 讨论(0)
  • 2020-12-05 02:43

    Firstly the if.. then .. else is better, for numerous reasons pointed out by the other posters.

    However it is not necceseraly faster! It depends entirly on the ration of null objects to not null objects. It probably takes a hundreds of thousands times the resources to process an exception rather than test for null, however, if a null object occurs only once for every million objects then the exception option will be slightly faster. But not that much faster that its worth making your program less readable and harder to debug.

    0 讨论(0)
  • 2020-12-05 02:47

    Definitely second form is much faster. In the try-catch scenario, it throws an exception which does a new Exception() of some form. Then the catch block is invoked which is a method call and has to execute whatever code is in it. You get idea.

    0 讨论(0)
  • 2020-12-05 02:48

    This issue has discussed recently by Dr. Heinz:

    http://javaspecialists.eu/webinars/recordings/if-else-npe-teaser.mov

    0 讨论(0)
提交回复
热议问题