Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw and catch an exception, or use instanceof?

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();
}
like image 526
Ruslan Avatar asked Dec 06 '13 19:12

Ruslan


People also ask

How do you know if a method throws an exception?

The calculate method should check for an exception and if there is no exception, return the calculated value to the main function i.e. v1+v2 or v1-v2; Else if an exception exists then it should print the error statement and the value that is returned from the calculate method to the main method should be 0.0(Not ...

What is the use of try throw and catch statements?

The try statement defines a code block to run (to try). The catch statement defines a code block to handle any error. The finally statement defines a code block to run regardless of the result. The throw statement defines a custom error.

How do you handle multiple exceptions in java?

Java Catch Multiple Exceptions A try block can be followed by one or more catch blocks. Each catch block must contain a different exception handler. So, if you have to perform different tasks at the occurrence of different exceptions, use java multi-catch block.

Can we use try and catch for exception handling?

The try statement allows you to define a block of code to be tested for errors while it is being executed. The catch statement allows you to define a block of code to be executed, if an error occurs in the try block.


4 Answers

I'd advise using instanceof as 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't happen. Exceptions should be exceptional.

Note that the throw technique 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 instanceof technique), which might or might not be helpful, depending on how you want to handle exceptions that are not one of the specific sub-types.

like image 178
Boann Avatar answered Oct 18 '22 22:10

Boann


Hate to burst everyone's bubble, but using try/catch is 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:

Run 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

Run 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

Run 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

Test environment

  • Java: 1.7.0_45
  • Mac OSX Mavericks

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

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

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;
        }
    }
}
like image 30
disrvptor Avatar answered Oct 18 '22 23:10

disrvptor


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.String is 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...).

like image 4
Elliott Frisch Avatar answered Oct 18 '22 22:10

Elliott Frisch


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.

like image 3
Joe Avatar answered Oct 19 '22 00:10

Joe