有没有办法注释方法,所以抛出的所有异常都会自动转换为运行时异常?
@MagicAnnotation
// no throws clause!
void foo()
{
throw new Exception("bar")'
}
答案 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
了解详情