当前位置: 首页 > 知识库问答 >
问题:

编译器在检查异常时没有显示任何错误

赵俊侠
2023-03-14

我正在处理检查的异常,并在两者之间发现编译器在检查的异常上没有显示任何错误并且工作正常的情况。

import java.io.FileNotFoundException;

interface A {
    void f() throws FileNotFoundException;
}

interface B {
    void f() throws InterruptedException;
}

interface C extends A, B {
}

public class Test implements C {
    public void f() {
        System.out.println("Hello world");
    }

    public static void main(String[] args) {
        C obj = new Test();
        obj.f(); // Working fine and printing "Hello World"
    }
}

请让我知道原因,我谷歌了很多,但没有找到任何东西。

共有3个答案

司毅庵
2023-03-14

一个方法可以抛出的检查异常集是它声明在所有适用类型中抛出的检查异常集的交集,而不是联合[JLS 15.12.2.5]。编译器只检查方法声明中的异常。

interface InterfaceA{
    void f() throws AException;
}
interface InterfaceB{
    void f() throws BException;
}
interface InterfaceC extends InterfaceA, InterfaceB {
    void f();                                     //correct one
    void f() throws AException;                   //cannot pass compile
    void f() throws BException;                   //cannot pass compile
    void f() throws AException, BException;       //cannot pass compile
}

InterfaceC中的方法f()只能在{AException}和{BException}的交叉点抛出异常,因此没有。该规则限制了方法可以处理的异常。

interface InterfaceA{
    void f() throws AException, CException;
    void g() throws AException, CException;
}
interface InterfaceB{
    void f() throws BException, CException;
    void g() throws BException, CException;
}
interface InterfaceC extends InterfaceA, InterfaceB {
    void g();
}
public class C implement InterfaceC {
    public void f() {}
    public void g() {}
    public static void main(String[] args) {
        InterfaceC interfaceC = new C();
        C c = new C();
        interfaceC.f();                          //cannot pass compile, must handle Exception CException
        c.f();                                   //compile passed
        interfaceC.g();                          //compile passed
    }
}

InterfaceC中的方法f()未声明,因此此方法是自动生成的,异常列表为{CException},是InterfaceA中的{AException,CException}与InterfaceB中的{BException,CException}的交集。IntrefaceC中的方法g()和C类中的方法f()都是在没有任何异常的情况下声明的,因此无需进行异常处理即可通过编译。

沈成天
2023-03-14

这个问题的答案是正确的,但我想补充一些澄清。各种评论和回答都表明,在代码中

C obj = new Test();
obj.f();

不需要处理任何检查过的异常的原因是“因为实现不会抛出任何检查过的异常”。这不是问题所在。实现是Test。f()。但是obj。f()正在调用C.f()。编译器在编译时没有查看实现。它正在查看C中的规范。

您可以通过编写

void doThing(C obj) {
    obj.f();
}

即使不编写实现C的类,也可以编译它。

现在doThing不知道正在调用f的什么实现,但它仍然知道它不会抛出任何检查过的异常,因为C. f()不能抛出A. f()B. f()未声明的检查过的异常。C. f()可能抛出的一组检查过的异常是其两个超接口抛出的一组检查过的异常的交集。

劳华灿
2023-03-14

用面向对象的术语来说,当你编程到一个接口(即实现一个接口或扩展一个接口)时,你不能比接口更严格。然而,你可以减少限制。因此,在您的示例中,接口的方法可能会也可能不会引发FileNotFoundException和/或InterruptedException,但您的实现方法不会引发异常。请注意,如果您的实现的方法抛出FileNotFoundException和/或InterruptedException,则完全可以,但如果它抛出其他异常,则不允许。这意味着您的实现的限制性可以等于或小于接口,但不能比接口更严格。

还要注意,当有人通过扩展接口类型(C)的变量或类类型(Test)的变量使用方法f()时,他们不需要处理异常。但是,如果他们通过接口类型a或B的变量使用方法f(),他们需要处理异常。

A obj = new Test(); 
obj.f(); // need to handle FileNotFoundException

B obj = new Test();
obj.f(); // need to handle InterruptedException

C obj = new Test(); 
obj.f(); // don't need to handle any of the exceptions

Test obj = new Test(); 
obj.f(); // don't need to handle any of the exceptions

更多说明:C. f()不抛出异常的原因是它的父接口抛出了不同的异常。因此,根据“接口的实现或扩展不能更严格,但可以更少限制”的论点,C. f()限制较少的唯一方法是不抛出异常。否则,它将比它的至少一个父接口更具限制性。另一方面,如果C的两个父接口都抛出了相同的异常,那么C. f()也需要抛出这些异常。但是,实现仍然可以选择不抛出异常。

import java.io.FileNotFoundException;

interface A{
    void f() throws FileNotFoundException;
}

interface B {
    void f() throws FileNotFoundException;
}

interface C extends A, B {
}

public class Test implements C {
    public void f() {
        System.out.println("Hello world");
    }

    public static void main(String[] args) {
        C obj = new Test();
        obj.f(); // Compilation error, unhandled exception

        Test obj = new Test();
        obj.f(); // No error
    }
}
 类似资料:
  • 寻求帮助,将TypeScript编译器报告的类型错误输入到ESLint的输出中。库typescript eslint(https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/TYPED_LINTING.md)让我觉得这应该是可能的。 文件结构 .eslintrc.

  • 问题内容: 调用显示编译时错误,并显示以下消息: getSupportFragmentManager()。getFragments()只能在同一库组中调用(groupId = com.android.support) 我在中导入了以下类: 延伸。 我的项目模块级别文件如下: 这是inside 方法的源代码。 我最近将Android Studio更新到了最新的稳定版本(2.3),并且还更新了Andr

  • 我想知道如何在Android Studio中显示编译错误。我试了下面这个:

  • 我被困了几个小时,无法释放它。 它给了我常规的通常我会在代码中的某个地方发现错误,或者只是在模块上运行inspector,它会检测错误,修复错误后,构建工作正常。 这一次,我和检查员都没有发现代码中的任何错误。 它发生在我试图整合Algolia之后。但是我试图恢复我所做的一切,错误仍然存在。我如何摆脱它? 编辑:我现在看到kotlin编译器给了我错误。它说有几个函数: 在我的设置中,kotlin被

  • 例如如下代码: SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); Date date = sdf.parse("abcd"); 这段代码会抛出ParseException,而它是编译时异常,为什么编译阶段不报错,运行时报错?

  • 我们的团队试图从GWT 2.4.0升级到2.5.0,但现在我们面临的问题是编译器引发了一个异常。以下是编译器日志: 绑定:用户。代理=safari绑定:编译器。useSourceMaps=true绑定:locale=en编译模块应用程序。m8。网状物AGM验证单元:第一次通过时忽略了3个有编译错误的单元。编译时将-strict或-logLevel设置为TRACE或DEBUG以查看所有错误。[错误]