4

考虑以下场景

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规范中g,它将报告 A。

但这很痛苦,因为

  • 这是一个两步过程
  • 我可能无法控制f更改其投掷规格的功能。

有没有更好的方法让编译器报告所有异常?

我并不是说编译器在这里做错了什么——我要问的是——“有没有办法让编译器报告所有异常?”。或者是否有一个工具可以帮助我自动获取这些信息。

该函数f在不同情况下抛出 A & B。如果我是. g_ g_ 有没有办法让编译器检测到这一点并警告我。gthrows Athrows B, A

同样,我并不是说编译器没有警告我这样做是错误的。我要问的是是否有办法让编译器做我想做的事。或者报告这个的工具?

4

2 回答 2

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 没有针对您想要的内容进行预定义的检查。事实上,它确实有一个完全相反的检查。

因此,您可能必须为它编写自己的检查,但 Checkstyle 很容易做到这一点。我会先阅读RedundantThrows检查的源代码,然后做相反的事情。如果您没有在方法throws签名中列出所有抛出的检查异常,这应该会使您的自定义检查失败。

于 2013-09-21T16:20:42.587 回答
1

这是编译器特定的行为。在 Eclipse 中包含您的场景时,编译器将在错误列表中告知这两个异常,尽管工具提示中只显示一个异常。更有趣的是,当使用自动修复时,无论是添加catch子句还是throws声明,Eclipse 都将始终添加两者(换句话说:所有异常),而忽略异常之间的任何子类关系。声明的顺序对此行为没有影响。所以也许你只想使用 Eclipse :^)。

于 2013-09-24T13:06:22.190 回答