简体   繁体   English

如何避免在包装类中重复复杂的异常处理代码?

[英]How to avoid repeating complex exception handling code in a wrapper class?

I have this class that wraps an object: 我有这个包装对象的类:

public class MyWrapper implements MyInterface {

    private MyInterface wrappedObj;

    public MyWrapper(MyInterface obj) {
        this.wrappedObj = obj;
    }

    @Override
    public String ping(String s) {
        return wrappedObj.ping(s);
    }

    @Override
    public String doSomething(int i, String s) {
        return wrappedObj.doSomething(i, s);
    }

// many more methods ...
}

Now I want to add complex exception handling around the wrappedObj call. 现在我想在wrappedObj调用周围添加复杂的异常处理。

It is the same for all the methods. 所有方法都是一样的。

How do I avoid repeating the same exception handling code over and over? 如何避免反复重复相同的异常处理代码?

If your exception handling is fully generic you could implement the wrapper as InvocationHandler : 如果您的异常处理是完全通用的,您可以将包装器实现为InvocationHandler

public class ExceptionHandler implements java.lang.reflect.InvocationHandler {
    public ExceptionHandler(Object impl) {
        impl_ = impl;
    }

    @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return method.invoke(impl_, args);
        }
        catch (Exception e) {
            // do exception handling magic and return something useful
            return ...;
        }
    }

    private Object impl_;
}

and then wrap it around an instance as follows: 然后将其包装在实例中,如下所示:

MyInterface instance = ...
MyInterface wrapper = (MyInterface)java.lang.reflect.Proxy.newProxyInstance(
   instance.getClass().getClassLoader(), 
   new Class[] { MyInterface.class }, 
   new ExceptionHandler(instance));

wrapper.ping("hello");

If you want to avoid the cost of reflection, than just use a router function. 如果你想避免反射的成本,而不仅仅是使用路由器功能。

@Override
public String ping(String s) {
    return (String) call("ping");
}

private Object call(String func) {
    try {
      switch(func) {
        case "ping": return wrappedObj.ping(s);
        // ... rest of functions ... //
      }
    } catch(Exception e) {
      log(e);
    }
}

The compiler can than effectively just jump to the function without pulling up Object specs or handlers. 编译器可以有效地跳转到函数而不需要提取Object规范或处理程序。 (A smart enough compiler may even just compile this to identical execution code as your current code, especially if you can cut the cast by always returning the same kind of object) (一个足够聪明的编译器甚至可以将它编译为与当前代码相同的执行代码,特别是如果你可以通过总是返回相同类型的对象来剪切强制转换)

If you don't care about the thread and just want a default exception handler... 如果你不关心线程,只想要一个默认的异常处理程序......

For the whole Java Runtime, call Thread.setDefaultUncaughtExceptionHandler 对于整个Java Runtime,请调用Thread.setDefaultUncaughtExceptionHandler
For a ThreadGroup, override ThreadGroup.uncaughtException 对于ThreadGroup,重写ThreadGroup.uncaughtException
For a single Thread, call Thread.setUncaughtExceptionHandler 对于单个Thread,请调用Thread.setUncaughtExceptionHandler

The advantage to a default handler, is that you can then add specific error handlers where needed, but the down side is you do lose the executing thread on error. 默认处理程序的优点是,您可以根据需要添加特定的错误处理程序,但不好的一面是您在错误时丢失执行的线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM