为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

蝴蝶刀刀 2021-12-10 16:29:56
我真的很难理解异常处理是如何工作的。为什么最好为我自己的用户定义的异常扩展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);    }  }}
查看完整描述

2 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

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() 方法只打印您放入其中的内容。


查看完整回答
反对 回复 2021-12-10
?
德玛西亚99

TA贡献1770条经验 获得超3个赞

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


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


对于您自己的例外:


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


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


在极不可能的情况下,您正在编写符合 an 定义的代码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的实现方式与Throwable'stoString的实现方式不同。您所做的也println与您最初展示的不同(使用字符串连接),尽管它没有什么大的不同。toString无论如何都会使用您的实例。


查看完整回答
反对 回复 2021-12-10
  • 2 回答
  • 0 关注
  • 147 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信