考虑以下情况
public class A extends Throwable {}
public class B extends A {}
public class C
{
public void f() throws A, B
{
// Some condition
throw new A();
// Some condition
throw new B();
}
void g()
{
f();
}
}
使用上面的代码,编译器将警告不要捕获(或不声明为抛出)
C.java:17: unreported exception A; must be caught or declared to be thrown
f();
^
如果我通过将g更改为
来解决此问题void g() throws A
然后我不再收到警告(B通过捕获A隐式捕获)
有没有办法让编译器报告所有未捕获的异常,包括基类异常(如此处的B)。
一种方法是更改g()
并将其声明为
public void f() throws B, A
在这种情况下,编译器将首先报告B&将{B}添加到throw
的{{1}}规范后,它会报告A。
但这很痛苦,因为
g
来改变它的投射规格。有没有更好的方法让编译器报告所有异常?
我并不是说编译器在这里做错了 - 我要问的是 - “有没有办法让编译器报告所有异常?”。或者是一个帮助我自动获取此信息的工具。
函数f
抛出A& B在不同的情况下。如果我是f
的作者,我不会意外地压制调用g
可能会抛出B的信息 - 如果我将g
声明为g
会发生什么而不是将其声明为throws A
。有没有办法让编译器检测到这一点并警告我。
同样,我并不是说编译器做错了而没有警告我反对。我要问的是,是否有办法让编译器按我的意愿行事。还是报告这个的工具?
答案 0 :(得分:3)
我并不想让人光顾或任何东西。我可能会说很多你已经知道的东西。但请耐心等待,同时我尝试解释为什么使用编译器警告无法解决您的问题。
相互派生两个类,不管它们是否是异常类,意味着它们处于 is-a 关系中。例如:
public class Vehicle {}
public class Car extends Vehicle {}
public class Boat extends Vehicle {}
表示:Car
是 Vehicle
。 Boat
是 Vehicle
。
使用throws
或更多点catch
(稍后),指定要投掷/被捕获的类型。现在,假设Vehicle
来自Exception
,您可以这样做:
try
{
// ...
}
catch (Car c)
{
// You caught a car. Not any vehicle, a real, honking car.
}
然而,通过这样做:
try
{
// ...
}
catch (Vehicle v)
{
// You caught some vehicle. Any vehicle.
}
您指定您不关心是否抓住汽车,船只,自行车或其他任何东西,只要它可以移动并运送乘客或货物。因为汽车是车辆。船是车辆。
总而言之,您要做的事情完全违背了面向对象方法的想法。您不能让编译器报告任何“被抑制”或“隐藏”的异常,因为它们真的不是。使用throws
时,它们的定义非常明确,而catch
则处理得非常多。所以编译器甚至不了解你的问题,更不用说提供一些方法来阻止它了。
正如评论所说,静态代码分析几乎是做你想做的事情的唯一选择。我在这些场合使用过的东西是Checkstyle。既然你想要的是非常不寻常的,我认为Checkstyle没有预定义的检查你想要什么。事实上,它需要检查the exact opposite。
所以你可能需要自己编写支票,但Checkstyle可以很容易地做到这一点。我将首先阅读RedundantThrows
检查的源代码,然后执行相反的操作。如果您未在方法throws
签名中列出所有抛出的已检查异常,则应使自定义检查失败。
答案 1 :(得分:1)
这是编译器特定的行为。在Eclipse中使用场景时,编译器会告诉错误列表中的两个异常,尽管工具提示中只显示了一个。更有趣的是,当使用自动修复时,要么添加catch
子句或throws
声明,Eclipse将始终添加两者(换句话说:所有异常),忽略异常之间的任何子类关系。声明的顺序对此行为没有影响。所以也许你只想使用Eclipse:^)。