[英]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
的实现方式与Throwable
的toString
的实现方式不同。 您还执行了与最初显示的不同的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 的简短描述。 * 结果是: *
*
* 如果 {@code getLocalizedMessage} 返回 {@code null},则只返回类名。 * * @return 这个 throwable 的字符串表示。 */ 公共字符串 toString()- 此对象的类的{@linkplain Class#getName() name} *
- ":"(一个冒号和一个空格)*
- 调用此对象的 {@link #getLocalizedMessage} * 方法的结果 *
所以,如果你覆盖它,就像你的例子一样。 您不再获得它的好处,您的 toString() 方法只打印您放入其中的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.