使用注释通过运行时异常包装异常

时间:2009-06-27 10:23:44

标签: java exception annotations runtimeexception

有没有办法注释方法,所以抛出的所有异常都会自动转换为运行时异常?

@MagicAnnotation
// no throws clause!
void foo()
{
  throw new Exception("bar")'
}

8 个答案:

答案 0 :(得分:6)

Project Lombok的@SneakyThrows可能就是你要找的东西。是不是真的包装你的异常(因为它在很多情况下可能是一个问题),它只是在编译期间不会抛出错误。

@SneakyThrows
void foo() {
    throw new Exception("bar")'
}

答案 1 :(得分:2)

您可以使用AspectJ执行此操作。你声明一个连接点(在这种情况下调用方法foo)并“软化”异常。

修改详细说明:

假设您有以下课程Bar

public class Bar {

    public void foo() throws Exception {
    }
}

......你有这样的测试:

import junit.framework.TestCase;

public class BarTest extends TestCase {

    public void testTestFoo() {
        new Bar().foo();
    }
}

然后显然测试不会编译。它会出错:

Unhandled exception type Exception  BarTest.java(line 6)

现在用AspectJ克服这个问题,你写了一个非常简单的方面:

public aspect SoftenExceptionsInTestCode {

    pointcut inTestCode() : execution(void *Test.test*());

    declare soft : Exception : inTestCode();
}

方面基本上表示在AspectJ中接受来自Test中的任何代码(即:以“Test”结尾并以“Test”结尾并返回'void'的类中以“test”开头的方法)抛出异常编译器。如果发生异常,它将被AspectJ编译器包装并抛出为RuntimeException

实际上,如果你从Eclipse中运行这个测试作为AspectJ项目的一部分(安装了AJDT),那么测试将成功,而没有方面,它甚至不会编译。

答案 2 :(得分:1)

我认为可以使用字节码重新设计,自定义编译器或可能面向方面的编程 1 。与Java相反,C#只有未经检查的异常 2

我可以问你为什么要压制已检查的异常?

根据 Maarten Winkels

1 这是可能的。
根据一些第9频道的视频, 2 他们正在考虑引入已检查的视频。

编辑:对于这个问题:从某种意义上说,您可以注释您的方法,将它们标记为检查异常抑制的候选者。然后使用一些编译时或运行时技巧来应用实际的抑制/包装。

但是,由于我没有看到您的案例周围的环境,以这些方式包装异常可能会混淆该方法的客户端 - 他们可能没有准备好处理RuntimeException。例如:该方法抛出IOException,您的客户端将其捕获为FileNotFoundException以显示错误对话框。但是,如果将异常包装到RuntimeException中,则永远不会显示错误对话框,并且可能也会导致调用者线程死亡。 (IMHO)。

答案 3 :(得分:1)

Checked异常是方法实现的责任。 非常仔细地考虑这个事实。如果你不能使用这样的解决方法工件。

答案 4 :(得分:1)

无法做到这一点,至少现在我使用这样的解决方法(简化):

@SuppressWarnings({"rawtypes", "unchecked"})
public class Unchecked {
    public static interface UncheckedDefinitions{
        InputStream openStream();
        String readLine();
            ...
    }

  private static Class proxyClass = Proxy.getProxyClass(Unchecked.class.getClassLoader(), UncheckedDefinitions.class);

    public static UncheckedDefinitions unchecked(final Object target){
        try{
            return (UncheckedDefinitions) proxyClass.getConstructor(InvocationHandler.class).newInstance(new InvocationHandler(){
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if (target instanceof Class){
                        return MethodUtils.invokeExactStaticMethod((Class) target, method.getName(), args);
                    }

                  return MethodUtils.invokeExactMethod(target, method.getName(), args);
                }
            });
        }
        catch(Exception e){
            throw new RuntimeException(e);
        }
    }
}

用法如下:

import static ....Unchecked.*;

...

Writer w = ...;
unchecked(w).write(str, off, len);

诀窍是接口“永远不会完成”,每当我需要在某个地方使用未经检查的方法时,我会将该对象包装成未经检查的,让IDE在接口中生成方法签名。

然后

实现是通用的(反射性和“慢速”,但通常足够快)

有一些代码后处理器和字节码编织器,但这对我当前的项目来说是不可能的(甚至不是aop或其他基于jvm的语言),所以这是“发明的”。

答案 5 :(得分:0)

你可以在任何情况下通过使用Class.newInstance 包裹Exception中的no-arg构造函数抛出的InvocationTargetException这一事实来执行此操作};而是它静静地

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

然后您可以在任何地方使用此实用程序:

ExUtil.throwSilent(new Exception());
//or
try {
  ioMethod();
} catch (IOException e) { ExUtil.throwSilent(e); }

顺便说一句,一个非常糟糕的主意: - )

答案 6 :(得分:0)

我使用Eclipse的完成/模板系统轻松地包装任何代码块。

这是我的模板:

try { // Wrapp exceptions

${line_selection}${cursor}

} catch (RuntimeException e) { // Forward runtime exception
throw e;
} catch (Exception e) { // Wrap into runtime exception
throw new RuntimeException(
    "Exception wrapped in #${enclosing_method}", 
    e); 
}

答案 7 :(得分:-3)

使用Java 8,它就像:soften(() -> methodThatMayThrow())

一样简单

http://iirekm.blogspot.com/2014/05/fix-problems-with-java-checked.html

了解详情