9.2.6 异常程的运行过E?/h4>
Q?Qfinally语句不被执行的唯一情况是先执行了用于终止程序的System.exit()Ҏ?br />
Q?Qreturn语句用于退出本Ҏ?br />
Q?Qfinally代码块虽然在return语句之前被执行,但finally代码块不能通过重新l变量赋值来改变return语句的返回倹{?br />
Q?Q徏议不要在finally代码块中使用return语句Q因为它会导致以下两U潜在的错误
AQ覆盖try或catch代码块的return语句
public class SpecialException extends Exception {
public SpecialException() {
}
public SpecialException(String msg) {
super(msg);
}
}
public class FinallyReturn {
/**
* @param args
*/
public static void main(String[] args) {
FinallyReturn fr = new FinallyReturn();
System.out.println(fr.methodB(1));// 打印100
System.out.println(fr.methodB(2));// 打印100
}
public int methodA(int money) throws SpecialException {
if (--money <= 0) {
throw new SpecialException("Out of money");
}
return money;
}
@SuppressWarnings("finally")
public int methodB(int money) {
try {
return methodA(money);// 可能抛出异常
} catch (SpecialException e) {
return -100;
} finally {
return 100;// 会覆盖try和catch代码块的return语句
}
}
}
BQ丢失异?br />
public class ExLoss {
/**
* @param args
*/
public static void main(String[] args) {
try {
System.out.println(new ExLoss().methodB(1));// 打印100
System.out.println("No Exception");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public int methodA(int money) throws SpecialException {
if (--money <= 0) {
throw new SpecialException("Out of money");
}
return money;
}
@SuppressWarnings("finally")
public int methodB(int money) {
try {
return methodA(money);// 可能抛出异常
} catch (SpecialException e) {
throw new Exception("Wrong");
} finally {
return 100;// 会丢失catch代码块中的异?/span>
}
}
}
9.3 Java异常c?/h3>
所有异常类的祖先类为java.lang.Throwablec,它的实例表示具体的异常对象,可以通过throw语句抛出?br />
ThrowablecL供了讉K异常信息的一些方法,常用的方法包括:
- getMessage() --q回Stringcd的异怿息?
- printStachTrace()--打印跟踪Ҏ调用栈而获得的详细异常信息。在E序调试阶段Q此Ҏ可用于跟t错误?
public class ExTrace {
/**
* @param args
*/
public static void main(String[] args) {
try {
new ExTrace().methodB(1);
} catch (Exception e) {
System.out.println("--- Output of main() ---");
e.printStackTrace();
}
}
public void methodA(int money) throws SpecialException {
if (--money <= 0) {
throw new SpecialException("Out of money");
}
}
public void methodB(int money) throws Exception {
try {
methodA(money);
} catch (SpecialException e) {
System.out.println("--- Output of methodB() ---");
System.out.println(e.getMessage());
throw new Exception("Wrong");
}
}
}
打印l果Q?br />
--- Output of methodB() ---
Out of money
--- Output of main() ---
java.lang.Exception: Wrong
at chapter09.d0903.ExTrace.methodB(ExTrace.java:45)
at chapter09.d0903.ExTrace.main(ExTrace.java:26)
ThrowablecL两个直接子类Q?br />
- Errorc?-表示仅靠E序本n无法恢复的严重错误,如内存不等?
- Exceptionc?-表示E序本n可以处理的异常?
9.3.1 q行时异?/h4>
RuntimeExceptioncd其子c都被称行时异常Q这U异常的特点是Java~译器不会检查它Q会~译通过Q但q行时如果条件成立就会出现异常?br />
例如当以下divided()Ҏ的参数b?Q执?#8220;a/b”操作时会出现ArrithmeticException异常Q它属于q行时异常,Java~译器不会检查它?br />
public int divide2(int a, int b) {
return a / b;// 当参Cؓ0Q抛出ArrithmeticException
}
下面的程序中的IllegalArgumentException也是q行时异常,divided()Ҏx有捕获它Q也没有声明抛出它?br />
public class WithRuntimeEx {
/**
* @param args
*/
public static void main(String[] args) {
new WithRuntimeEx().divide(1, 0);
System.out.println("End");
}
public int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("除數不能?");
}
return a / b;
}
}
׃E序代码不会处理q行时异常,因此当程序在q行时出Cq种异常Ӟ׃DE序异常l止。以上程序的打印l果为:
Exception in thread "main" java.lang.IllegalArgumentException: 除數不能?
at chapter09.d0903.WithRuntimeEx.divide(WithRuntimeEx.java:29)
at chapter09.d0903.WithRuntimeEx.main(WithRuntimeEx.java:23)
9.3.2 受检查异?/h4>
除了RuntimeException及其子类以外Q其他的Exceptioncd其子c都属于受检查异常(Checked ExceptionQ。这U异常要么catch语句捕获Q要么throws子句声明抛出Q否则编译出错?br />
9.3.3 区分q行时异常和受检查异?/h4>
受检查异常表C程序可以处理的异常?br />
q行时异常表C无法让E序恢复q行的异常,Dq种异常的原因通常是由于执行了错误操作。一旦出C错误操作Q徏议终止程序,因此Java~译器不查这U异常?br />
9.3.4 区分q行时异常和错误
Errorcd其子c表C程序本w无法修复的错误Q它和运行时异常的相同之处是QJava~译器都不会查它们,当程序运行时出现它们Q都会终止程序?br />
两者的不同之处是:Errorcd其子c表C的错误通常是由Java虚拟机抛出?br />
而RuntimeExceptionc表C程序代码中的错误,它是可扩展的Q用户可以根据特定的问题领域来创建相关的q行时异常类?br />
9.4 用户定义异常
9.4.1 异常转译和异帔R
public class BaseException extends Exception {
protected Throwable cause = null;
public BaseException() {
}
public BaseException(String msg) {
super(msg);
}
public BaseException(Throwable cause) {
this.cause = cause;
}
public BaseException(String msg, Throwable cause) {
super(msg);
this.cause = cause;
}
public Throwable initCause(Throwable cause) {
this.cause = cause;
return this;
}
public Throwable getCause() {
return cause;
}
public void printStackTrace() {
printStackTrace(System.err);
}
public void printStackTrace(PrintStream outStream) {
printStackTrace(new PrintStream(outStream));
}
public void printStackTrace(PrintWriter writer) {
super.printStackTrace(writer);
if (getCause() != null) {
getCause().printStackTrace(writer);
}
writer.flush();
}
}
9.4.2 处理多样化异?/h4>
public class MultiBaseException extends Exception {
protected Throwable cause = null;
private List<Throwable> exceptions = new ArrayList<Throwable>();
public MultiBaseException() {
}
public MultiBaseException(Throwable cause) {
this.cause = cause;
}
public MultiBaseException(String msg, Throwable cause) {
super(msg);
this.cause = cause;
}
public List getException() {
return exceptions;
}
public void addException(MultiBaseException ex) {
exceptions.add(ex);
}
public Throwable initCause(Throwable cause) {
this.cause = cause;
return this;
}
public Throwable getCause() {
return cause;
}
public void printStackTrace() {
printStackTrace(System.err);
}
public void printStackTrace(PrintStream outStream) {
printStackTrace(new PrintStream(outStream));
}
public void printStackTrace(PrintWriter writer) {
super.printStackTrace(writer);
if (getCause() != null) {
getCause().printStackTrace(writer);
}
writer.flush();
}
}
9.5 异常处理原则
9.5.1 异常只能用于非正常情?/h4>
9.5.2 为异常提供说明文?/h4>
9.5.3 可能地避免异常
9.5.4 保持异常的原子?/h4>
9.5.5 避免q于庞大的try代码?/h4>
9.5.6 在catch子句中指定具体的异常cd
9.5.7 不要在catch代码块中忽略被捕L异常Q可以处理异常、重新抛出异常、进行异常{?/h4>

]]>