列出所有未报告的异常(包括超出声明的异常类的异常)

时间:2013-09-19 05:11:24

标签: java exception static-analysis throws

考虑以下情况

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。有没有办法让编译器检测到这一点并警告我。

同样,我并不是说编译器做错了而没​​有警告我反对。我要问的是,是否有办法让编译器按我的意愿行事。还是报告这个的工具?

2 个答案:

答案 0 :(得分:3)

我并不想让人光顾或任何东西。我可能会说很多你已经知道的东西。但请耐心等待,同时我尝试解释为什么使用编译器警告无法解决您的问题。

相互派生两个类,不管它们是否是异常类,意味着它们处于 is-a 关系中。例如:

public class Vehicle {}

public class Car extends Vehicle {}

public class Boat extends Vehicle {}

表示:Car VehicleBoat 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:^)。

相关问题