Java中的检查异常与未检查异常

Java中的检查异常与未检查异常,java,exception,Java,Exception,我在理解Java中checked和unchecked异常之间的区别时遇到了一些问题 首先,checked异常应该在编译时查找异常。不同来源中提供的示例引用了数据库连接、文件处理等,而unchecked异常应该查找程序员方面的错误,例如索引超出数组范围等 不是应该反过来吗?我的意思是,数据库连接是在运行时完成的,对吗?文件处理也是如此。您在编译时不打开文件句柄,那么为什么在编译时会查找该句柄上可能存在的错误呢?另一方面,程序中已经对超出其范围的数组进行了索引,这可以在编译时进行检查(如果异常索引是

我在理解Java中
checked
unchecked
异常之间的区别时遇到了一些问题

  • 首先,
    checked
    异常应该在编译时查找异常。不同来源中提供的示例引用了数据库连接、文件处理等,而
    unchecked
    异常应该查找程序员方面的错误,例如索引超出数组范围等
  • 不是应该反过来吗?我的意思是,数据库连接是在运行时完成的,对吗?文件处理也是如此。您在编译时不打开文件句柄,那么为什么在编译时会查找该句柄上可能存在的错误呢?另一方面,程序中已经对超出其范围的数组进行了索引,这可以在编译时进行检查(如果异常索引是由用户在运行时提供的,则可以将其视为运行时问题)。我错过了什么

    2其次,
    RunTimeException
    ,它本身是
    未选中的
    ,子类
    Exception
    ,即
    已选中的
    ,它如何能够执行呢?这意味着什么

    我在Herbert Schildt的书中找到了一个例子,解释了
    checked
    异常的用法:

    class ThrowsDemo {
       public static char prompt(String str)
          throws java.io.IOException {
      System.out.print(str + ": ");
      return (char) System.in.read();
      }
      public static void main(String args[]) {
        char ch;
        try {
          ch = prompt("Enter a letter");
        }
        catch(java.io.IOException exc) {
         System.out.println("I/O exception occurred.");
         ch = 'X';
        }
        System.out.println("You pressed " + ch);
        }
    }
    
    这里是否需要
    抛出
    子句?为什么我不能像这样用
    try-catch
    语句正常执行(很抱歉,我不知道如何模拟
    IO异常,所以我自己无法检查它!):

  • 您不需要在
    throws
    子句中声明未经检查的异常;但您必须声明选中的异常
  • RuntimeException
    Error
    ,以及它们的所有子类(
    IllegalArgumentException
    stackoverflowerr
    等)都是未加密的异常;
    RuntimeException
    是未选中的,这一事实与其他可丢弃的
    子类不同,是出于设计
    
  • 没有所谓的“编译时异常”
  • 更一般地说,在JVM错误或程序员错误的情况下,会抛出未经检查的异常。一个著名的此类异常是
    NullPointerException
    ,通常缩写为NPE,它是
    RuntimeException
    的子类,因此未选中

    未检查异常和已检查异常之间的另一个非常重要的区别是,在try-catch块中,如果要捕获未检查异常,必须显式捕获它们

    最后注意:如果您有异常类
    E1
    E2
    E2
    扩展
    E1
    ,那么捕获和/或抛出
    E1
    也会捕获/抛出
    E2
    。这表示已检查和未检查的异常。这对
    catch
    块有影响:如果确实区分了catch
    E2
    E1
    ,则必须首先捕获
    E2

    例如:

    // IllegalArgumentException is unchecked, no need to declare it
    public void illegal()
    {
        throw new IllegalArgumentException("meh");
    }
    
    // IOException is a checked exception, it must be declared
    public void ioerror()
        throws IOException
    {
        throw new IOException("meh");
    }
    
    // Sample code using illegal(): if you want to catch IllegalArgumentException,
    // you must do so explicitly. Not catching it is not considered an error
    public void f()
    {
        try {
            illegal();
        } catch (IllegalArgumentException e) { // Explicit catch!
            doSomething();
        }
    }
    

    我希望这能让事情变得更清楚…

    编译器只会确保一个方法在没有声明的情况下不能抛出一个选中的异常。一般认为,编译器应该对发生在程序员控制之外的异常进行检查,例如您引用的示例(数据库连接、文件丢失等)。未检查的异常“不应该发生”,因此编译器不会强制您声明它们

    至于模拟
    IOException
    或任何其他异常,它是微不足道的:

    throw new IOException();
    
    在您的示例中,
    prompt
    方法可能会抛出一个
    IOException
    ,这就是它需要声明它的原因。这与调用方法时如何处理异常无关


    RuntimeException
    Exception
    的一个子类,可以方便地用一个
    catch Exception
    子句捕获所有异常。这本可以有不同的设计;Java的异常类层次结构很混乱。

    如果您不在这里放入throws子句,则会发生此错误

    ThrowsDemo.java:5:未报告的异常java.io.IOException;一定要被抓住,否则就被抓住 被抛出去的 return(char)System.in.read()

    因此,在必要时加入该条款


  • 否。所有异常都发生在运行时。选中异常是强制调用方处理或声明它们的异常。它们通常用于发出可恢复错误的信号,这些错误不是由程序员错误(如文件不存在或网络连接问题)引起的。运行时异常通常用于表示不可恢复的错误。它们不会强制调用方处理或声明它们。它们中的许多确实发出了编程错误的信号(比如NullPointerException)

  • 因为这就是JLS定义未检查异常的方式:一个是或扩展RuntimeException的异常,它本身扩展了异常。使用单个继承根允许在单个catch子句中处理所有可能的异常


  • 关于您的示例:是的,throws子句是强制性的,因为IOException是一个选中的异常,并且方法中的代码容易抛出异常。

    CheckedException需要由调用方处理,而未选中的异常则不需要

    因此,在设计应用程序时,您应该考虑您正在管理的是哪种异常情况

    例如,如果您设计了一个验证方法来检查某些用户输入的有效性,那么您知道调用方必须检查验证异常并以美观的方式向用户显示错误。这应该是一个选中的异常

    Unchecked Exception
       -- NullPointerException
       -- ArrayIndexOutofBound
       -- IllegalArgument Exception
       -- ClassCastException
       -- IllegalStateException
       -- ConcurrentModificationException
    
    Checked Exception Five Example
       -- FileNotFoundException
       -- ParseException
       -- ClassNotFoundException
       -- CloneNotSupportException
       -- SQLException
    
    或者,对于那些可以恢复的异常情况:假设您有一个负载平衡器,您希望通知调用者“n”台服务器中的一台已关闭,因此调用者必须恢复事件,并将消息重新路由到另一台服务器;这
    Unchecked Exception
       -- NullPointerException
       -- ArrayIndexOutofBound
       -- IllegalArgument Exception
       -- ClassCastException
       -- IllegalStateException
       -- ConcurrentModificationException
    
    Checked Exception Five Example
       -- FileNotFoundException
       -- ParseException
       -- ClassNotFoundException
       -- CloneNotSupportException
       -- SQLException