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

Java压倒一切的投掷条款

祁鸿哲
2023-03-14

我通过阅读S G Ganesh和Tushar Sharma写的书来学习OCJP考试。在第346页,有一段文字说:

如果你试着改变投掷条款呢?在重写方法中更改throws子句的方法有很多,包括以下方法:
a。不提供任何抛出子句。列出要抛出的更多常规检查异常。除了基本方法中给定的已检查异常之外,还列出了更多已检查异常。
如果尝试这三种情况中的任何一种,都会得到编译器错误。例如,尝试不在实现IntReader接口的类中的readIntFromFile()方法中提供throws子句。

public int readIntFromFile() {
    Scanner consoleScanner = new Scanner(new File("integer.txt"));
    return consoleScanner.nextInt();
}

你会得到这个编译器错误:“未报告的异常FileNotFoundExcema;必须被捕获或声明被抛出。”
总而言之,基类方法的抛出子句是它提供给该方法调用者的契约:
它说调用者应该处理列出异常或在其throws子句中声明这些异常。当重写基本方法时,派生方法也应该遵守该契约。基方法的调用方准备只处理基方法中列出的异常,因此重写方法不能抛出比列出的检查异常更通用或其他的异常。
但是,请注意,派生类方法的抛出子句应该遵循基本方法的抛出子句的约定仅限于检查过的异常。与基类方法的throws子句相比,仍然可以从契约中html" target="_blank">添加或删除未检查的异常。例如,考虑以下情况:

public int readIntFromFile() throws IOException, NoSuchElementException {
    Scanner consoleScanner = new Scanner(new File("integer.txt"));
    return consoleScanner.nextInt();
}

这是一个可接受的throws子句,因为可以从readIntFromFile()方法中抛出NoTouchElementException。此异常是未经检查的异常,当nextInt()方法无法从文件中读取整数时,会引发此异常。这是一种常见的情况,例如,如果您有一个名为integer的空文件。txt;尝试从此文件读取整数将导致此异常。

我有点担心a点。它说,如果不提供任何throws子句,代码将无法编译。但是当我学习OCA时,我记得我读到过,您可以提供相同的throws子句,一个更具体的Exception或no throws子句,代码仍然可以编译,并且这些仅适用于检查过的异常。我尝试过做一些测试,但无法获取“未报告的异常文件NotFoundException;必须捕获或声明要抛出”。我记得我见过它,但我不知道在什么情况下。

共有3个答案

常心水
2023-03-14

这本书是错的:

class A {
    public void foo() throws FileNotFoundException {

    }
}

class B extends A {
    public void foo() {

    }
}

对于这样的语言特性,最好参考Java语言规范。

秦安宁
2023-03-14

正如马努蒂所说,这本书是错的。您肯定可以有更精确或无例外,但不能有更一般的例外:

interface A {
    void meth() throws IOException;
}

class B implements A {
    @Override
    void meth() throws FileNotFoundException { } // compiles fine
}

class C implements A  {
    @Override
    void meth() { } // compiles fine
}

class D implements A  {
    @Override
    void meth() throws Exception { } // compile error
}
丁淇
2023-03-14

这本书在A点上错了。

以下代码编译得非常好:

class A {
    void method() throws GeneralSecurityException {
    }
}

class B extends A {
    void method() {
    }
}

B显然使点A无效。

这本书也过于简单化了C点:只要抛出的异常是已经抛出的检查异常的子类,代码就是正确的。

class C extends A {
    void method() throws NoSuchAlgorithmException, InvalidKeyException {
    }
}

在代码NoSuchAlgorithmExceptionInvalidKeyException中,是GeneralSecurityException的子类。

C显示了点C的过度简化。

以下是Java语言规范Java SE 8版第11.2章中的说明:

...

抛出条款中指定的已检查异常类(§11.1.1)是方法或构造函数的实现者和用户之间合同的一部分。重写方法的throws子句不能指定该方法将导致抛出任何被重写方法不允许抛出的已检查异常(§8.4.8.3)。

...

8.4.8.3中的参考内容如下:

...

  • 如果m2有一个throws子句提到任何检查过的异常类型,那么m1必须有一个throws子句,否则会发生编译时错误。
  • 对于m2throws子句中列出的每个检查异常类型,相同的异常类或其超类型之一必须在throws m1的code>子句;否则,将发生编译时错误。

...

这些JLS章节很有意义。最后,调用声明特定检查异常的方法的代码将具有处理特定检查异常的代码。如果子类实例的方法引发另一个选中的异常,则不太可能处理选中的异常。另一方面,如果方法没有抛出调用方所期望的任何异常,则调用方是OK的;异常处理代码将不会被调用。

代码应该总是希望收到运行时异常,因此基于RuntimeException的异常可以免于编译时检查。

只要您只抛出调用方期望的异常,代码就应该是正常的。

 类似资料:
  • 有人可以解释我什么时候使用关键字 throw new 有用.而不是在方法的签名旁边使用抛出? 我知道当方法抛出Checked Exception时。Java迫使我们通过将Exception处理到try-catch块中,或者通过在签名旁边的关键字throws指定将在其他地方完成,从而直接在方法中处理它。 然而,我很难理解何时使用关键字throw new是有用的,以及为什么。它与处理未选中的异常有关吗

  • 我在视图中有一个ImageView,并尝试用它显示一个WritableImage实例。我正在外线程中绘制它,并通过侦听ObjectProperty的更改事件将其传递给视图。 imageView应该准备好接收图像,它由我的主视图显示。但是这是一个不合法的例外 线程“Thread-4”Java . lang . illegalstateexception中的异常:不在FX应用程序线程上;当前线程=线程

  • 我正在用python运行下面的代码 我每次都会遇到下面的错误-有人能帮忙吗! OpenCV错误:未指定的错误(该函数未实现。使用Windows、GTK 2.x或Carbon支持重建库。如果您在Ubuntu或Debian上,请安装libgtk2.0-dev和pkg config,然后重新运行cmake或configure脚本),位于cvShowImage、file/Users/travis/buil

  • 我有两个类(SimManager和Sim),我想为它们创建模拟对象,然后使用存根方法。 测试在上面第9行抛出这两个错误跟踪。 第一: Java语言lang.VerifyError:org/mockito/cglib/core/reflectils at org。莫基托。cglib。果心KeyFactory$发电机。在org上生成Class(KeyFactory.java:167)。莫基托。cgli

  • 我有下面的代码,它按照预期工作: 我想知道是否有一种方法,只有一个orElseThrow-Part,或做它更少的冗余?

  • 我向服务器调用一个请求网络,服务器总是响应如下所示的格式json: 对于每种请求,只有jsonObject数据包含不同的字段。新响应的示例: 因此,我决定让一个通用类调用ServerResult包含一个字段“Object”,以便将其强制转换为特定对象。 //ServerResult.class //client.java 请求完成后,我通过GSON将json转换为ServerResult对象: 然