Is there a way to annotate a method so all exceptions thrown are converted to runtime exception automagically?
@MagicAnnotation
// no throws clause!
void foo()
{
throw new Exception("bar")'
}
Is there a way to annotate a method so all exceptions thrown are converted to runtime exception automagically?
@MagicAnnotation
// no throws clause!
void foo()
{
throw new Exception("bar")'
}
You can do this with AspectJ. You declare a joinpoint (in this case invocation of the method foo) and 'soften' the exception.
Edit To elaborate a bit on this:
Say you have the following class Bar
:
public class Bar {
public void foo() throws Exception {
}
}
...and you have a test like this:
import junit.framework.TestCase;
public class BarTest extends TestCase {
public void testTestFoo() {
new Bar().foo();
}
}
Then obviously the test is not going to compile. It will give an error:
Unhandled exception type Exception BarTest.java(line 6)
Now to overcome this with AspectJ, you write a very simple aspect:
public aspect SoftenExceptionsInTestCode {
pointcut inTestCode() : execution(void *Test.test*());
declare soft : Exception : inTestCode();
}
The aspect basically says that any code from within a Test (i.e.: a method that starts with "test" in a class that ends in "Test" and returns 'void') that throws an exception should be accepted by the AspectJ compiler. If an exception occurs, it will be wrapped and thrown as a RuntimeException
by the AspectJ compiler.
Indeed, if you run this test as part of an AspectJ project from within Eclipse (with AJDT installed) then the test will succeed, whereas without the aspect it won't even compile.
I think it is possible with bytecode re-engineering, customized compiler or perhaps aspect oriented programming1. In the contrary to Java, C# has only unchecked exceptions2.
May I ask why you want to suppress the checked exceptions?
1 according to Maarten Winkels this is possible.
2 and they are thinking about introducing checked ones, according to some Channel 9 videos.
Edit: For the question: It is possible in the sense that you can annotate your methods to flag them to be a candidate for checked exception suppression. Then you use some compile time or runtime trick to apply the actual suppression / wrapping.
However, as I don't see the environment around your case, wrapping an exception in these ways might confuse the clients of that method - they might not be prepared to deal with a RuntimeException. For example: the method throws an IOException and your clients catches it as FileNotFoundException to display an error dialog. However if you wrap your exception into a RuntimeException, the error dialog gets never shown and probably it kills the caller thread too. (IMHO).
The way I do it without annotations is to have a method wrapper which calls the desired method with exceptions and all inside a
try {
methodThrowingLotsOfExceptions();
} catch (RuntimeException e) {
// avoid wrapping if not needed
throw e;
} catch (Exception e)
throw new RuntimeException("wrapped thrown exception from method()", e);
}
This avoids the try-catch inside the troublesome method allowing for better readability, without putting code "away" in an annotation .
--
Edit: Personally I believe that checked exceptions have their merit, in saying "You - the programmer - CAN handle this, please consider what should be done". It really helps in considering border cases when doing the original design, which usually means that the design is better fittet for actually handeling border cases. (Instead of some poor maintainer having to wring the inside out, to get the code to handle a customer problem. "Oh, you don't want the application to crash if the network drive is unavailable...")
In your particular case, you actually have considered this (and decided you don't want to think anymore about it). You may also want to subclass your exceptions saying what caused the problem, this will alllow you to handle this better upstream. Here I think that instead of just throwing a RuntimeException("Network drive unavailable") you may want to create a NetworkDriveUnavailableException() instead so your CODE can be more readable and robust if you catch this at a higher level.
You can do this in any case via use of the fact that Class.newInstance
does not wrap an Exception
thrown by the no-arg constructor in an InvocationTargetException
; rather it throws it silently:
class ExUtil {
public static void throwSilent(Exception e) { //NOTICE NO THROWS CLAUSE
tl.set(e);
SilentThrower.class.newInstance(); //throws silently
}
private static ThreadLocal<Exception> tl = new ThreadLocal<Exception>();
private static class SilentThrower {
SilentThrower() throws Exception {
Exception e = tl.get();
tl.remove();
throw e;
}
}
}
Then you can use this utility anywhere:
ExUtil.throwSilent(new Exception());
//or
try {
ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }
By the way, this is a really bad idea :-)