繁体   English   中英

当我自己用参数字符串抛出异常时究竟会发生什么? 什么时候调用 toString 方法?

[英]What exactly happens when I throw an exception myself with a parameter string? When does the toString method get called?

我真的很难理解异常处理是如何工作的。 为什么最好为我自己的用户定义的异常扩展Exception而不是Throwable类?

try {
   //some SQL exception
} 
catch(SQLException e) {
  System.out.println(e);
} 

e在这里实际上代表什么? 我知道它是对 SQL 异常对象的引用,但它会打印什么? 它会调用toString方法吗?

编辑:当我覆盖toString方法和从我的源代码中完全删除它时,我得到的输出非常不同。 请解释为什么?

class MyException extends Throwable {
  private int detail;

  MyException(String msg) {
    super(msg);
  }

  public String toString() {
    return "MyException[" + detail + "]";
  } 
}

class ExceptionDemo {
  static void compute(int a) throws MyException {  // cant be thrown as throwable 
    System.out.println("Called compute(" + a + ")");
    if(a > 10)
      throw new MyException("MyException class error");
    System.out.println("Normal exit");
  }

  public static void main(String args[]) {
    try {
      compute(1);
      compute(20);
    } catch (MyException e) {
      System.out.println("Caught " + e);
    }
  }
}

> 为什么最好为我自己的用户定义的异常扩展 throwable 而不是 Exception 类?

不是。 您已编辑问题以将其反转为:

为什么最好为我自己的用户定义的异常扩展 Exception 而不是 Throwable 类?

因为一般来说,异常应该是Exceptions 线索就在名字里。 :-) Throwable不是一个例外,它是一个 throwable。 (也就是说,JDK 中的Throwable / Error / Exception / RuntimeException层次结构通常被认为布局不佳。例如,奇怪的是Throwable及其子类被检查,其子类Exception被检查,但它的子类RuntimeException没有被检查,还有另一个Throwable子类Error ,它也是未经检查的。我相信这是出于历史原因,而不是因为它的设计很棒。)

对于您自己的例外:

  • 如果应该检查您的异常,则扩展Exception (或其子类之一,而不是RuntimeException )。

  • 如果您的异常应该是unchecked ,请扩展RuntimeException (或其子类之一)。

  • 不可能的情况下,您正在编写符合Error定义的代码,您可以子类化该代码或其子类之一,但我认为我从未见过包含Error子类的代码库。 大多数情况下, Error是针对 JVM 级别的错误,例如“内存不足”。

 try { //some SQL exception} catch(SQLException e) {System.out.println(e);}

e在这里实际上代表什么? 我知道它是对 SQL 异常对象的引用...

是的,它是 SQLException 的实例或其子类。

...但它会打印什么? 它会调用 toString 方法吗?

是的,间接地: PrintStream#println(Object)调用String.valueOf(Object) ,它在对象上调用toString

当我覆盖 toString 方法和从我的源代码中完全删除它时,我得到的输出非常不同。 请解释为什么?

因为您的toString的实现方式与ThrowabletoString的实现方式不同。 您还执行了与最初显示的不同的println (使用字符串连接),尽管它没有太大区别。 无论如何都会使用您实例的toString

Throwable 是 Java 语言中所有错误和异常的超类。 它有两个直接的实现:错误和异常。 Error 是一个子类,它指示合理的应用程序不应尝试捕获的严重问题。 异常表示合理的应用程序可能想要捕获的条件。

因此,您不应创建实现 Throwable 的自定义异常,也不应捕获 Throwable,因为这样做也会捕获 Error 类型,并且预计不会缓存 Error。

还值得一提的是,有一个著名的 Exception 子类型:RuntimeException。 RuntimeException 是未经检查的异常,这意味着您可以抛出它们并且不会强制调用者捕获它。

多年来,关于使用 Exception 与 RuntimeException 的争论一直很激烈。 RuntimeException 赢了(当然有些人可能仍然认为相反),但在早期使用 Exception 被认为是王者,这就是为什么第一版本的几个 Java API 抛出 Exception 类型,而现代 Java API 和框架大部分时间都抛出 RuntnimeException。

至于

e在这里实际上代表什么? 我知道它是对 SQL 异常对象的引用,但它会打印什么? 它会调用 toString 方法吗?

你是对的,e 是 SQLException 类型的变量的名称,你可以在 catch 块中使用它。 它确实像每个 Object 在 System.out.println() 中添加时那样调用它的 toString 方法。

编辑:当我覆盖 toString 方法和从我的源代码中完全删除它时,我得到的输出非常不同。 请解释为什么?

在您的示例中,您正在扩展 Throwable,如前所述,您不应该这样做。 所有扩展 Throwable 的类都将使用它的 toString() 实现,它的文档说:

/** * 返回此 throwable 的简短描述。 * 结果是: *

    *
  • 此对象的类的{@linkplain Class#getName() name} *
  • ":"(一个冒号和一个空格)*
  • 调用此对象的 {@link #getLocalizedMessage} * 方法的结果 *
* 如果 {@code getLocalizedMessage} 返回 {@code null},则只返回类名。 * * @return 这个 throwable 的字符串表示。 */ 公共字符串 toString()

所以,如果你覆盖它,就像你的例子一样。 您不再获得它的好处,您的 toString() 方法只打印您放入其中的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM