This should be a low-level process, and it doesn't mean we cannot have the same thing with current level, but it may needs a bunch of code and would complex the system a little.
However my suggestion would be like this(I hope I got it correct), first define an interface for who wants to process exceptions, something like this.
interface ExceptionHandler{
void handleException(Throwable t);
}
then provide an annotation for user(API) to mark its methods may throws some exception.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@interface Catch{
public Class<? extends ExceptionHandler> targetCatchHandler();
public Class<? extends Throwable> targetException() default Exception.class;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface CatchGroup{
public Catch[] catchers();
}
next we need a interface to start to call the method which may throws exception, something like this.
interface Caller{
void callMethod()throws Throwable;
}
then you need a guy who take care and manage the flow of the execution and call the possible exception handler
class MethodCaller{
/*
* @param isntance: instance which implemented the Caller interface
*/
public static void callMethod(Caller instance)
throws Exception {
Method m = instance.getClass().getMethod("callMethod");
Annotation as[] = m.getAnnotations();
Catch[] li = null;
for (Annotation a : as) {
if (a.annotationType().equals(CatchGroup.class)) {
li = ((CatchGroup) a).catchers();
}
// for(Catch cx:li){cx.targetException().getName();}
}
try {
instance.callMethod();
} catch (Throwable e) {
Class<?> ec = e.getClass();
if (li == null) {
return;
}
for (Catch cx : li) {
if (cx.targetException().equals(ec)) {
ExceptionHandler h = cx.targetCatchHandler().newInstance();
h.handleException(e);
break;
}
}
}
}
}
and finally, lets have some example, it works very well for me, it's cool.
the exception handler.
public class Bar implements ExceptionHandler{//the class who handles the exception
@Override
public void handleException(Throwable t) {
System.out.println("Ta Ta");
System.out.println(t.getMessage());
}
}
and the method caller.
class Foo implements Caller{//the class who calls the method
@Override
@CatchGroup(catchers={
@Catch(targetCatchHandler=Bar.class,targetException=ArithmeticException.class),
@Catch(targetCatchHandler=Bar.class,targetException=NullPointerException.class)})
public void callMethod()throws Throwable {
int a=0,b=10;
System.out.println(b/a);
}
public static void main(String[] args) throws Exception {
Foo foo=new Foo();
MethodCaller.callMethod(foo);
}
}
as you see, the user HAS TO call the methods by the callmethod()
method, you would also omit the Caller
interface, and use annotation to declare more than one method in a class that it needs a bunch of extra codez.
I hope I could give some hand.