To boldly throw checked exceptions where no one has thrown them before!
@SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method's
throws clause. This somewhat contentious ability should be used carefully, of course. The code generated by lombok will not ignore, wrap, replace, or otherwise modify the thrown checked exception; it simply fakes out the compiler. On the JVM (class file) level, all exceptions, checked or not, can be thrown regardless of the
throws clause of your methods, which is why this works.
Common use cases for when you want to opt out of the checked exception mechanism center around 2 situations:
A needlessly strict interface, such as
Runnable- whatever exception propagates out of your
run()method, checked or not, it will be passed to the
Thread's unhandled exception handler. Catching a checked exception and wrapping it in some sort of
RuntimeExceptionis only obscuring the real cause of the issue.
An 'impossible' exception. For example,
new String(someByteArray, "UTF-8");declares that it can throw an
UnsupportedEncodingExceptionbut according to the JVM specification, UTF-8 must always be available. An
UnsupportedEncodingExceptionhere is about as likely as a
ClassNotFoundErrorwhen you use a String object, and you don't catch those either!
Being constrained by needlessly strict interfaces is particularly common when using lambda syntax (
arg -> action); however, lambdas cannot be annotated, which means it is not so easy to use
@SneakyThrows in combination with lambdas.
Be aware that it is impossible to catch sneakily thrown checked types directly, as javac will not let you write a catch block for an exception type that no method call in the try body declares as thrown. This problem is not relevant in either of the use cases listed above, so let this serve as a warning that you should not use the
@SneakyThrows mechanism without some deliberation!
You can pass any number of exceptions to the
@SneakyThrows annotation. If you pass no exceptions, you may throw any exception sneakily.
Supported configuration keys:
error] (default: not set)
Lombok will flag any usage of
@SneakyThrowsas a warning or error if configured.
@SneakyThrows is an implementation detail and not part of your method signature, it is an error if you try to declare a checked exception as sneakily thrown when you don't call any methods that throw this exception. (Doing so is perfectly legal for
throws statements to accommodate subclasses). Similarly,
@SneakyThrows does not inherit.
For the nay-sayers in the crowd: Out of the box, Eclipse will offer a 'quick-fix' for uncaught exceptions that wraps the offending statement in a try/catch block with just
e.printStackTrace() in the catch block. This is so spectacularly non-productive compared to just sneakily throwing the exception onwards, that Roel and Reinier feel more than justified in claiming that the checked exception system is far from perfect, and thus an opt-out mechanism is warranted.
If you put
@SneakyThrows on a constructor, any call to a sibling or super constructor is excluded from the
@SneakyThrows treatment. This is a java restriction we cannot work around: Calls to sibling/super constructors MUST be the first statement in the constructor; they cannot be placed inside try/catch blocks.
@SneakyThrows on an empty method, or a constructor that is empty or only has a call to a sibling / super constructor results in no try/catch block and a warning.