首页 文章

Java重写throws子句

提问于
浏览
4

我正在通过阅读S G Ganesh和Tushar Sharma撰写的书来学习OCJP考试 . 在页346上有一个文字说:

如果您尝试更改throws子句怎么办?在重写方法中有许多方法可以更改throws子句,包括:a . 不提供任何抛出条款 . 湾列出要抛出的更多常规检查异常 . C . 除了基本方法中给定的已检查异常外,还列出了更多已检查的异常 . 如果您尝试这三种情况中的任何一种,您将收到编译器错误 . 例如,尽量不要在实现IntReader接口的类中的readIntFromFile()方法中提供throws子句 . public int readIntFromFile(){
扫描仪consoleScanner =新扫描仪(新文件(“integer.txt”));
return consoleScanner.nextInt();
}
您将收到此编译器错误:“未报告的异常FileNotFoundException;必须被捕获或声明被抛出 . “总而言之,基类方法的throws子句是它为该方法的调用者提供的 Contract :它表示调用者应该处理列出的异常或在其throws子句中声明这些异常 . 覆盖基本方法时,派生方法也应遵守该 Contract . 基本方法的调用者准备只处理基本方法中列出的异常,因此覆盖方法不能抛出更一般的或不是列出的已检查异常 . 但是,请注意,派生类方法的throws子句应遵循基本方法的throws子句的约定的讨论仅限于已检查的异常 . 与基类方法的throws子句相比,仍可以在 Contract 中添加或删除未经检查的异常 . 例如,请考虑以下内容:public int readIntFromFile()throws IOException,NoSuchElementException {
扫描仪consoleScanner =新扫描仪(新文件(“integer.txt”));
return consoleScanner.nextInt();
}
这是一个可接受的throws子句,因为可以从readIntFromFile()方法抛出NoSuchElementException . 此异常是未经检查的异常,当nextInt()方法无法从文件中读取整数时,它会被抛出 . 这是一种常见情况,例如,如果您有一个名为integer.txt的空文件;尝试从此文件中读取整数将导致此异常 .

我有点担心“a . ”这一点 . 它说如果你不提供任何throws子句,代码将无法编译 . 但是当我学习OCA时,我记得我读过你可以提供相同的throws子句,一个更具体的Exception或者没有throws子句,代码仍然会编译,这些只适用于Checked Exceptions . 我试过做一些测试,但我不能得到“未报告的异常FileNotFoundException;必须被抓或宣布被抛出 . “我记得我看过它,但我不知道在哪种情况下 .

5 回答

  • 2

    正如马努蒂所说,这本书是错误的 . 你肯定可以有更精确或没有例外,但你不能有一个更普遍的:

    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
    }
    
  • 2

    反例A点

    A点上的这本书是错误的 .

    以下代码编译完全正常:

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

    B 明显使A点无效 .

    反例C点

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

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

    在代码中 NoSuchAlgorithmExceptionInvalidKeyExceptionGeneralSecurityException 的子类 .

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

    JLS参考

    以下是The Java Language Specification, Java SE 8 Edition, chapter 11.2中的状态:

    ... throws子句中命名的已检查异常类(第11.1.1节)是方法或构造函数的实现者和用户之间的 Contract 的一部分 . 重写方法的throws子句可能没有指定此方法将抛出任何被抛出的方法不允许被抛出的方法抛出的任何已检查异常抛出(§8.4.8.3) . ...

    8.4.8.3中的引用如下:

    ...如果m2有一个throws子句提到任何已检查的异常类型,那么m1必须有一个throws子句,否则会发生编译时错误 . 对于m2的throws子句中列出的每个已检查异常类型,在m1的throws子句的擦除(第4.6节)中必须出现相同的异常类或其超类型之一;否则,发生编译时错误 . ...

    讨论JLS文本

    这些JLS章节是有道理的 . 最后,调用声明特定已检查异常的方法的代码将具有处理该特定已检查异常的代码 . 如果子类实例的方法抛出另一个已检查的异常,则不太可能处理已检查的异常 . 另一方面,如果方法没有抛出调用者期望的任何异常,则调用者是可以的;根本不会调用异常处理代码 .

    代码应始终期望接收运行时异常,因此基于 RuntimeException 的异常免于编译时检查 .

    经验法则

    只要您只抛出调用者期望的异常,代码就可以了 .

  • 0

    好吧,这本书错了:

    class A {
        public void foo() throws FileNotFoundException {
    
        }
    }
    
    class B extends A {
        public void foo() {
    
        }
    }
    

    编译确定 . 对于这样的语言特性,最好参考Java语言规范 .

  • 1

    这本书混合了两件事 . 它讨论的是子类中的重写throws子句,但它提供的示例与此完全无关:

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

    你会在这里得到一个编译错误,因为 Scanner 构造函数会抛出 FileNotFoundException ,它不会在 readIntFromFile() 中被捕获或传播 . 也就是说,从 readIntFromFile() 的声明中可以看出它可能会引发异常 .

    仅当子类中的方法调用其超级方法时,这适用于子类/基类:

    class A {
        void meth() throws IOException {
            // ...
        }
    }
    
    class B extends A {
        @Override
        public
        void meth() { 
            super.meth(); // compile error here
            // ...
        }
    }
    
  • 0

    java.io.Printwritter/PrintStream :: close() java中的api是在超类抛出的 IOException 的最佳示例( java.io.OutputStream :: close() )在子类中被忽略 .

    还有一件事是

    try {
       //CheckedExceptionX must be thrown from here
    }
    catch(CheckedExceptionX e) {
    }
    

    然而

    public void someAPI throws CheckedExceptionX {
         //trowing CheckedExceptionX is not mandatory in this method
         //Means this body can be free from throwing that mentioned CheckedException 
    }
    

相关问题