通过总结运行时异常异常与注释
-
20-08-2019 - |
题
有一种方法来注释的方法,从而抛出被转换为运行时异常所有异常自动的?
@MagicAnnotation
// no throws clause!
void foo()
{
throw new Exception("bar")'
}
解决方案
没有办法做到这一点,至少在目前我使用的解决方法是这样的(简化的):
@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的语言),我目前的项目,所以这是“发明”。
其他提示
项目龙目岛的 @SneakyThrows
可能是你在找什么。是不是真的包装你的异常(因为它可以在很多情况下的问题),它只是没有在编译过程中抛出一个错误。
@SneakyThrows
void foo() {
throw new Exception("bar")'
}
您可以使用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被接受编译器。如果发生异常,它将被包裹并抛出由AspectJ编译一个RuntimeException
。
事实上,如果你在Eclipse中运行这个测试作为一个AspectJ项目的一部分(用AJDT安装),然后测试会成功,而无需方面它甚至不会编译。
我认为这是可能的字节码的重新设计,定制的编译器或也许面向方面的编程 1 。在相反的对Java,C#仅具有强制异常 2
我可以问你为什么要打压检查的异常?
1 根据马腾Winkels 这是可能的。结果 2 和它们正在考虑引入检查的,根据一些9频道的视频。
编辑:对于这样的问题:这是可能的,你可以注释你的方法来标记他们是经过检查的异常抑制候选人感。然后你使用一些编译时或运行伎俩应用的实际抑制/包装。
不过,我没有看到你周围的情况下,环境,包装在这些方面可能会混淆该方法的客户例外 - 他们可能没有准备好应对一个RuntimeException。例如:在方法抛出IOException异常和您的客户抓住它作为FileNotFoundException异常显示一个错误对话框。不过,如果你换你的例外成一个RuntimeException,错误对话框被从未显示,可能它杀死调用程序线程太多。 (IMHO)。
在经过例外是该方法的实施责任。 采取非常非常小心这个事实。如果你不使用的解决办法文物这样的。
您可以通过使用的事实,Class.newInstance
的不的包通过在Exception
无参数的构造函数抛出的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); }
顺便说一句,这是一个非常糟糕的主意: - )
我使用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);
}
使用的Java 8很容易,因为:soften(() -> methodThatMayThrow())
更多详情 HTTP://iirekm.blogspot的.com / 2014/05 / FIX-问题与 - java的checked.html