【问题标题】:How to avoid repeating complex exception handling code in a wrapper class?如何避免在包装类中重复复杂的异常处理代码?
【发布时间】:2017-10-17 06:45:42
【问题描述】:

我有一个包装对象的类:

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 ...
}

现在我想在 WrappedObj 调用周围添加复杂的异常处理。

所有方法都一样。

如何避免一遍又一遍地重复相同的异常处理代码?

【问题讨论】:

标签: java lambda exception-handling code-reuse


【解决方案1】:

如果您的异常处理是完全通用的,您可以将包装器实现为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_;
}

然后将其包裹在一个实例周围,如下所示:

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

wrapper.ping("hello");

【讨论】:

    【解决方案2】:

    如果你想避免反射的代价,那就不要只使用路由器功能。

    @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);
        }
    }
    

    编译器可以有效地直接跳转到函数而无需提取对象规范或处理程序。 (足够聪明的编译器甚至可以将其编译为与当前代码相同的执行代码,特别是如果您可以通过始终返回相同类型的对象来削减演员表)

    如果您不关心线程而只想要一个默认的异常处理程序...

    对于整个 Java 运行时,请致电 Thread.setDefaultUncaughtExceptionHandler
    对于 ThreadGroup,覆盖 ThreadGroup.uncaughtException
    对于单个线程,请致电Thread.setUncaughtExceptionHandler

    默认处理程序的优点是,您可以在需要时添加特定的错误处理程序,但缺点是您确实会在出错时丢失正在执行的线程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多