3. 设计一个新的异常类
在设计一个新的异常类时,首先看看是否真正的需要这个异常类。一般情况下尽量不要去设计新的异常类,而是尽量使用Java中已经存在的异常类。
如IllegalArgumentException, UnsupportedOperationException
不管是新的异常是chekced异常还是unChecked异常。我们都必须考虑异常的嵌套问题。
public void methodA()throws ExceptionA...{
…..
throw new ExceptionA();
}
方法methodA声明会抛出ExceptionA.
public void methodB()throws ExceptionB
methodB声明会抛出ExceptionB,当在methodB方法中调用methodA时,ExceptionA是无法处理的,所以ExceptionA应该继续往上抛出。一个办法是把methodB声明会抛出ExceptionA.但这样已经改变了MethodB的方法签名。一旦改变,则所有调用methodB的方法都要进行改变。
另一个办法是把ExceptionA封装成ExceptionB,然后再抛出。如果我们不把ExceptionA封装在ExceptionB中,就丢失了根异常信息,使得无法跟踪异常的原始出处。
public void methodB()throws ExceptionB...{
try...{
methodA();
……
}catch(ExceptionA ex)...{
throw new ExceptionB(ex);
}
}
如上面的代码中,ExceptionB嵌套一个ExceptionA.我们暂且把ExceptionA称为“起因异常”,因为ExceptionA导致了ExceptionB的产生。这样才不使异常信息丢失。
所以我们在定义一个新的异常类时,必须提供这样一个可以包含嵌套异常的构造函数。并有一个私有成员来保存这个“起因异常”。
public Class ExceptionB extends Exception...{
private Throwable cause;
public ExceptionB(String msg, Throwable ex)...{
super(msg);
this.cause = ex;
}
public ExceptionB(String msg)...{
super(msg);
}
public ExceptionB(Throwable ex)...{
this.cause = ex;
}
}
当然,我们在调用printStackTrace方法时,需要把所有的“起因异常”的信息也同时打印出来。所以我们需要覆写 printStackTrace方法来显示全部的异常栈跟踪。包括嵌套异常的栈跟踪。
public void printStackTrace(PrintStrean ps)...{
if(cause == null)...{
super.printStackTrace(ps);
}else...{
ps.println(this);
cause.printStackTrace(ps);
}
}
一个完整的支持嵌套的checked异常类源码如下。我们在这里暂且把它叫做NestedException
public NestedException extends Exception...{
private Throwable cause;
public NestedException (String msg)...{
super(msg);
}
public NestedException(String msg, Throwable ex)...{
super(msg);
This.cause = ex;
}
public Throwable getCause()...{
return (this.cause == null ? this :this.cause);
}
public getMessage()...{
String message = super.getMessage();
Throwable cause = getCause();
if(cause != null)...{
message = message + “;nested Exception is ” + cause;
}
return message;
}
public void printStackTrace(PrintStream ps)...{
if(getCause == null)...{
super.printStackTrace(ps);
}else...{
ps.println(this);
getCause().printStackTrace(ps);
}
}
public void printStackTrace(PrintWrite pw)...{
if(getCause() == null)...{
super.printStackTrace(pw);
}
else...{
pw.println(this);
getCause().printStackTrace(pw);
}
}
public void printStackTrace()...{
printStackTrace(System.error);
}
}
同样要设计一个unChecked异常类也与上面一样。只是需要继承RuntimeException。