1.异常处理的越早,损失越小
2.在一些传统的编程语言中,如C语言中,没有专门处理异常的机制,程序员通常用方法的特定返回值来表示异常情况。Java语言按照面向对象的思想来处理异常,使得程序具有更好的可维护性,Java语言处理异常具有以下优点:
>把各种不同类型的异常情况进行分类,用Java类来表示异常情况,这种类被称为异常类。把异常情况表示成异常类,可以充分发挥类的可扩展和可重用的优势
>异常流程的代码和正常流程的代码分离,提高了程序的可读性,简化了程序结构
>可以灵活的处理异常,如果当前方法有能力处理异常,就捕获并处理他,否则就只需要抛出异常,由方法调用者来处理
3.Java虚拟机的方法调用栈
每个线程都有一个独立的方法调用栈。对于Java应用程序的主线程,堆栈底部是程序的入口方法main(),当一个新的方法被调用时,Java虚拟机把描述改方法的栈结构置入栈顶,位于栈顶的方法为正在执行的方法。方法的调用顺序为:main()方法调用mathodB()方法,methodB()方法调用methodA()方法。
当一个方法正常执行完毕,Java虚拟机会从调用栈中弹出改方法的栈结构,然后继续处理前一个方法。如果在执行方法的过程中抛出异常,则Java虚拟机必须找到能捕获该异常的catch代码块。他首先检查看当前方法是否存在这样的catch代码块,若果存在就执行该catch代码块,否则Java虚拟机会从调用栈中弹出该方法的栈结构继续到前一个方法中查找合适的catch代码块。在回溯的过程中,若果Java虚拟机在某个方法中找到了处理改异常的代码块,则该方法的栈结构将成为栈顶元素,程序流程将转到改方法的异常处理代码部分继续执行。
当Java虚拟机追溯到调用栈的底部的方法时,如果仍没有找到处理改异常的代码块,将按照以下步骤处理
(1)调用异常对象的printStackTrace()方法,打印来自方法调用栈的异常信息,
(2)如果该线程不是主线程,那么终止这个线程,其他线程继续正常执行,如果该线程是主线程(即方法调用栈的底部为main()方法),那么整个应用程序终止。
public class MainCatcher {
public void methodA(int money) throws SpecialException{
if(--money <= 0){
throw new SpecialException("Out of money");
}
System.out.println("methodA");
}
public void methodB(int money) throws SpecialException{
methodA(money);
System.out.println("MethodB");
}
public static void main(String[] args) throws SpecialException {
new MainCatcher().methodB(1);
}
}
class SpecialException extends Exception{
public SpecialException() {
super();
// TODO Auto-generated constructor stub
}
public SpecialException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
打印的结果是
Exception in thread "main" com.gao.exception.SpecialException: Out of money
at com.gao.exception.MainCatcher.methodA(MainCatcher.java:10)
at com.gao.exception.MainCatcher.methodB(MainCatcher.java:16)
at com.gao.exception.MainCatcher.main(MainCatcher.java:21)
如果改成
public static void main(String[] args) throws SpecialException {
//new MainCatcher().methodB(1);
try {
new MainCatcher().methodB(1);
System.out.println("mian");
} catch (SpecialException e) {
System.out.println("Wrong");
}
}
打印的结果是 Wrong
如果new MainCatcher().methodB(2);
methodA
MethodB
mian
4.throws:生命可能会抛出的异常
如果一个方法可能会抛出异常,但是没有能力处理这种异常,可以在方法声明处使用throws字句来声明抛出异常。例如汽车在运行时可能会出现故障,汽车本身没有办法处理这个故障,因此Car()类的run()方法声明抛出CarWrongException。
Worker类的gotoWork()方法调用以上run()方法,gotoWork()方法捕获并处理CarWrongException异常,在异常处理过程中又生出新的异常LateException,gotoWork()方法本身不会再处理LateException而是声明抛出LateException。谁回来处理Worker类的LateException呢?显然是职工老板,如果某职工上班迟到,那么就扣他的工资。
public class Worker {
private Car car;
public Worker(Car car) {
super();
this.car = car;
}
public void gotoWork() throws LateException {
try {
car.run();
} catch (CarWrongException e) {
walk();
Date date = new Date(System.currentTimeMillis());
String reason = e.getMessage();
throw new LateException(date, reason);
}
}
private void walk() {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
}
}
class Car{
public void run() throws CarWrongException{
if(true/*车子无法刹车*/){
throw new CarWrongException("车子无法刹车");
}
if(true/*发动机无法启动*/){
throw new CarWrongException("发动机无法启动");
}
}
}
class CarWrongException extends Exception{
public CarWrongException() {
super();
// TODO Auto-generated constructor stub
}
public CarWrongException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
class LateException extends Exception{
private Date arriveTime;
private String reason;
public LateException(Date arriveTime, String reason) {
super();
this.arriveTime = arriveTime;
this.reason = reason;
}
public Date getArriveTime() {
return arriveTime;
}
public String getReason() {
return reason;
}
}