Most common checked and unchecked Java Exceptions?

Viewed 85668

As far as I understand, there is no way to find out which exceptions a method throws without looking up the API docs one-by-one.

Since that is no option, I'd like to reverse the research and ask you which are the most common Exceptions and RuntimeExceptions you've come across when dealing with:

  • Casting
  • Arrays
  • Vector, ArrayList, HashMap, etc.
  • IO (File class, streams, filters, ...)
  • Object Serialization
  • Threads (wait(), sleep(), etc.)
  • or anything else that is considered "basic Java"

I realize that this might be subjective and boring but it is for a class test and I really don't know better.

10 Answers

Assume the below are java.lang unless I specify otherwise:

  • Casting: ClassCastException
  • Arrays: ArrayIndexOutOfBoundsException, NullPointerException
  • Collections: NullPointerException, ClassCastException (if you're not using autoboxing and you screw it up)
  • IO: java.io.IOException, java.io.FileNotFoundException, java.io.EOFException
  • Serialization: java.io.ObjectStreamException (AND ITS SUBCLASSES, which I'm too lazy to enumerate)
  • Threads: InterruptedException, SecurityException, IllegalThreadStateException
  • Potentially common to all situations: NullPointerException, IllegalArgumentException

You would do well to look at Java site's Package Summary pages. Here's one: http://java.sun.com/j2se/1.4.2/docs/api/java/io/package-summary.html

As Bill K says. Checked exceptions are easy. If your IDE/program editor doesn't give you an quick way to see method javadocs or signatures you need to throw it away. Seriously.

Unchecked exceptions are a different kettle of fish. But I think the best strategy with unchecked exceptions is to not try to catch them. Instead, you write you code so that it avoids throwing them in the first place. For example;

// ... not sure if 'obj' is null
if (obj != null) {
    obj.someMethod();
}
// ... not sure if 'obj' has the right type
if (obj instanceof Foo) {
    Foo foo = (Foo) obj;
}
// ... not sure if 'i' is in range
if (i >= 0 && i < array.length) {
    .... = array[i];
}

Here's why I recommend this:

  • A guard test is orders of magnitude more efficient than throwing and catching an exception.
  • A guard test is more readable ... less lines of code.
  • If you catch an unchecked exception, you can never be sure that it happened for the reasons you think it did; for example:
    // obj might be null ...
    try {
        obj.doSomething();
    } catch (NullPointerException ex) {
        System.err.println("obj was null");  // WRONG!!!
        // the NPE could have happen inside doSomething()
    }
  • If an unchecked exception is caused by a bug, you DO want a stacktrace and (depending on the application) you MAY NOT want to recover.

Obviously, you only include these "guard" checks where your understanding of the code tells you that they are necessary! So, for example if you know that 'obj' ought to be non-null and 'i' ought to be in range, it is a good idea to leave the checks out. If you leave out one test too many, you'll get an exception ... but that's good because you can then use the stacktrace to figure out why your understanding of the code was wrong, and maybe fix the underlying bug.

I would like to contribute a list that groups by situation, which is probably more meaningful than grouping by packages or fields of programming.

Unexpected exceptions

These are exceptions that should ideally never be thrown in production. You should fix them instead of catching them and stfu.

when you test newly written code (and sometimes unexpectedly seen by users)

They should never happen again once you see them.

  • AssertionError
    • congratulations, you are writing good code
    • you should be happy that you made this error, because less (errors) is more (bugs)
    • I hope you won't end up finding out that your code is correct and you accidentally inverted your assertion
  • NullPointerException
    • where are your @NotNulls?
    • did you check before using the return value from Map.get()?
  • ArrayIndexOutOfBoundsException
    • do you check before using List.get()?
    • I hope you know well enough that Java isn't JavaScript, arrays are fixed-sized and you can't just array[array.length] = newElement
  • ClassCastException
    • too much generics is bad for your brain cells; consider moving to golang!
  • IllegalArgumentException
    • this could sometimes mean "read the fishing docs"

And less likely to see,

  • IllegalMonitorStateException
    • yes, having to synchronized sucks, but it's like this in most languages
  • CloneNotSupportedException
    • hey, just don't use clone(). aren't copy constructors cool?

And then you get more NullPointerException.

And then... Still NullPointerException? That @NotNull annotation is rubbish!

when you test newly written code for the 100th time

Exceptions that happen due to race conditions or rare probability. You should buy a lottery if you see them the first 10 times you run your code.

  • ConcurrentModificationException
    • ?your synchronized is where
  • IllegalStateException
  • StackOverflowError (not Exception)
    • have you tried tail recursion?

during compilation, deployment, etc.

They usually happen when you messed up the dependencies, used wrong versions of libraries, etc.

  • LinkageError
  • NoClassDefFoundError
  • java.lang.XxxNotFoundException, java.lang.NoSuchXxxException (classes, methods, etc.)
    • not reflections please

when you are too lazy

and when you are using @lombok.SneakyThrows or equivalent

  • RuntimeException
  • ? extends RuntimeException

Expected exceptions

If they are not caught, this probably means you are too lazy as well. You can't prevent them from throwing; you just have to catch them.

high likeliness

These exceptions have high likeliness to happen, and should always be handled specifically (i.e. you should actually handle them instead of just outputting the error)

  • NumberFormatException
    • I never understand why this exception extends RuntimeException.

medium likeliness

These exceptions sometimes happen due to invalid user input (but you should really validate them, so I classify these as "unexpected exceptions"), and sometimes happen due to system constraints that might not be reproducible when (non-stress) testing.

  • IOException and other java.io.XxxException
  • SecurityException
  • StackOverflowException
    • unfortunately, going to StackOverflow most likely won't fix your StackOverflowExceptions, because you will get more overflown stacks as you are looking for something to Ctrl-C and Ctrl-V
  • StackUnderflowException
    • no, StackOverflow is still not going to help a lot
  • OutOfMemoryError
    • I hope it's not a memory leak

Checked exceptions are easy, your editor should display the javadocs when you hover/complete the method name.

Unchecked are generally actual errors and aren't even in the javadocs more often than not. I guess the most common might be IllegalArgumentException, any method that has any possible combination of parameters that is invalid should throw it.

How about looking for subclasses of java.lang.exception, for example here

Personally I use 2 checked exceptions of my own TransientException for cases when a retry might work. And InvalidRequestException for validation errors.

Related