【问题标题】:can't java unchecked exceptions be handled using try/catch block?不能使用 try/catch 块处理 java 未经检查的异常吗?
【发布时间】:2011-11-12 12:21:13
【问题描述】:

在一个教程中,我发现 Unchecked Exception 不能由您的代码处理,即我们不能使用 try/catch 块,示例是像 ArrayIndexOutOfBoundsException, NullPointerException. 这样的异常,但这些异常可以是使用 try/catch 块处理。我想我不清楚这个概念!

另外我认为 throw 关键字只能与 try/catch 一起使用 block.can throw 关键字可以与 UncheckedException 一起使用吗?

【问题讨论】:

  • 你能发一个教程的链接吗?
  • 然后有 Errors 就像未经检查的异常,除了它们不是 Exceptions 并且您根本不应该捕获它们(但无论如何您都可以)。跨度>
  • 你甚至可以抛出Throwable 及其子类(它们既不是错误也不是异常)这些被编译器视为已检查异常。这些都被catch(Throwable t)抓到了
  • 教程有误。你在哪里读到的?否则它不会这么说,它只是说编译器不会强制捕获或抛出 RuntimeExceptions 和 Errors。

标签: java exception exception-handling


【解决方案1】:

已检查异常和未检查异常之间的唯一区别是,已检查异常必须使用throws 在方法签名中被捕获或声明,而对于未检查异常,这是可选的。

您的代码无法处理未经检查的异常,即我们不能使用 try/catch 块

当然可以 - 但我们不必这样做。

我还认为 throw 关键字只能与 try/catch 块一起使用。 throw 关键字可以与 Unchecked Exception 一起使用吗?

注意这里有两个关键字:

  • throw 显式抛出您创建的异常对象。 throw new NullPointerException(); 工作得非常好,但显式创建该特定异常并不常见,大多数人会认为这是一种糟糕的风格。
  • throws 声明一个方法可能会抛出该异常。对于未经检查的异常,这是可选的,但有助于记录事实(同样,通常不会声明 throws NullPointerException,因为这几乎是给定的)。

【讨论】:

  • 你为什么说抛出新的异常实例是不常见/不好的风格?无论如何,有人需要创建异常不是吗?
  • @Pacerier 我专门讨论的是 NullPointerException,它通常由 JRE 创建,而不是由 Java 代码创建。
  • 如果我们的函数需要一个非空输入但调用代码发送一个空输入,那么抛出一个新的NullPointerException(可选地包含在“非法参数”异常中,例如IllegalArgumentException)?另一种方法似乎是使用我们的变量好像它们不为空,并让 JRE 在我们的函数中途抛出一个NullPointerException,但这似乎很笨重,而且对意外错误不健壮。
  • @Pacerier:一个简单的 IllegalArgumentException 将是正确的选择
  • “当然可以——但我们不必这样做。”日志记录呢?
【解决方案2】:

所有未检查的异常都可以按照与检查的异常相同的方式处理 - 如果您愿意,可以通过声明方法 throws 他们让它们通过:

public void m() throws RuntimeException {}

或者你可以catch他们:

public void m() {
    try {
        // some code
    } catch (RuntimeException re) {
        // do something
    }
}

需要注意的是,RuntimeException 类作为未检查异常的包罗万象(因为所有未经检查的异常都从它扩展而来),与 Exception 类是包罗万象的方式非常相似用于检查的异常。

如前所述,唯一真正的区别是,对于已检查的异常,您必须处理它们(通过让它们通过或捕获它们)并且编译器将确保它 - 在另一方面,未检查异常的处理是可选的。

这一切都归结为每种异常类型的预期用法 - 您应该能够从检查的异常中恢复(或者至少在它们发生时对其进行处理),而对于未经检查的异常,可能没有是一种合理的方式来从它们中恢复过来。当然,这有点主观。

【讨论】:

  • 抓住 Trowable 不是更好吗?从link 可以看出,每一个错误和异常都是 Throwable 的后代。
  • @Kinnison84 是 bad practice 正是因为如此:你最终会捕捉到比你想象的更多的东西,而且有些东西没有意义。
【解决方案3】:

他们可以被处理,但你不必必须。如果您不处理它们,它们将传播并爬上调用方法堆栈,直到其中一个捕获它。如果没有,程序将崩溃。

通常,底线是,如果可以合理地期望客户端从异常中恢复,那么它应该是已检查异常。如果客户端无法从异常中恢复,则可以将其作为未经检查的异常

此外,已检查的异常对于记录您希望由 3rd 方使用的 API 很有用。当他们知道你的方法可以抛出一个特定的异常时,他们会相应地编码并处理这种情况。如果您只使用未经检查的例外情况,那么所有的赌注都会被取消。

一种常见的模式(有些人不喜欢它,但在某些情况下,当您知道自己在做什么时就可以了)是将抛出的已检查异常包装到未检查异常中。

try {
   ... code that can throw CheckedException ...
} catch (CheckedException oopsSomethingBadHappened) {
    throw new RuntimeException("Something bad happened!", oopsSomethingBadHappened);
}

【讨论】:

  • 我觉得使用该模式是为了方便开发者,但忽略了 API 用户需要做的额外工作来猜测开发者的想法。
【解决方案4】:

考虑差异的一种简单方法是认为检查是指编译。如果异常是已检查异常,编译器将在编译时检查您的代码是否抛出异常或在 try/catch 块中处理它。对于未经检查的异常,编译器不会做这样的检查。您可以以相同的方式处理已检查/未检查的异常(使用 try/catch/throws),区别仅在于编译器执行的检查。这篇文章有一个不错的example

【讨论】:

    【解决方案5】:

    除了纪尧姆:

    • 未经检查的异常通常是编程错误,如果正确实施(索引越界、空指针、类强制转换等)根本不会发生,因此调用者/用户通常无法对其执行任何操作。李>
    • 检查异常被抛出,因为它超出了程序员的控制(网络不可用,文件系统不可用,并发修改,例如重复的主键,...)
    • 错误通常由 JVM 抛出,应用程序通常必须停止(内存不足、堆栈溢出……)

    【讨论】:

      【解决方案6】:

      是的,您可以使用throw 抛出未经检查的异常。是的,您可以在 catch 块中捕获未经检查的异常。

      【讨论】:

      • 您也可以使用throws 显式传播它们,这是可选的,但可以使方法签名中的内容更加清晰。
      • @Thilo,嗯,抛出未经检查的异常?我想不出它会有用的情况......通常未经检查的异常意味着不会被捕获,因为它们代表编程错误并且您的程序应该在这种情况下崩溃。在我看来,对客户说你希望扔掉它们会让人感到困惑。您想到的是哪种情况?
      • Java SDK API 充满了throws IndexOutOfBoundsException 和朋友。请参阅download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html 以及@Michael 的回答。
      【解决方案7】:

      是的,您可以处理未经检查的异常,但不是强制性的。实际上,这取决于应用程序开发人员。以下是我认为需要处理未经检查的异常的可能原因。

      • 如果您的应用程序很大,许多开发人员互相调用 API。最好处理未经检查的异常,否则最后您的程序将崩溃,从而停止其他功能。所以即使是简单的 NullPointerException 也会让你的程序停止工作。

      • 假设您有一个调度程序来处理用户数据,其大小为百万,对于不良数据,您只想打印日志而不是停止为其他良好数据工作。在这种情况下,如果你没有处理异常,一个坏数据可能会停止你的程序

      【讨论】:

        【解决方案8】:

        是的,我们可以处理运行时异常,请检查下面的代码

        public class Demo {
          static void m1() {
            int a[]=new int [5];
            try {
            a[12]=2;
            }catch(Exception e) {
        
            }
          }
        
          public static void main(String[] args) {
            m1();
           try {
            String s=null;
        
            System.out.println(s.length());
           }catch(Exception e) {
        
           }
            System.out.println("hello world");
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-02-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多