Java编程思想读书笔记——通过异常处理错误(二)

12.7 Java标准异常

Throwable可以表示任何作为异常被抛出的类,其可分为两类对象:Error和Exception。

Error表示编译时和系统错误,一般不需关心;
Exception表示可以被抛出的基本类型,通常关心该类型。

异常的名称都是可以望文知意的。

12.7.1 特例:RuntimeException

运行时异常由Java虚拟机自动抛出,不必在异常说明中列出,在编译时也不检查这类异常,也无需捕获这类异常。

12.8 使用finally进行清理

finally子句,无论try块中是否抛出异常,finally子句中的代码都会被执行。

try {
    // The guarded region: Dangerous activities
    // that might throw A, B or C
} catch(A a1) {
    // Handler for situation A
} catch(B b1) {
    // Handler for situation B
} catch(C c1) {
    // Handler for situation C
} finally {
    // Activities that happen every time
}
12.8.1 finally用来做什么

把除内存之外的资源恢复到初始状态,就需要用到finally子句。如:
1) 已经打开的文件或网络连接;
2) 在屏幕上画的图形;
3) 外部世界的某个开关。

12.8.2 在return中使用finally

因为finally子句总是会被执行,所以在一个方法中,可以从多个点返回,并且可以保证重要的清理工作仍旧会被执行。

package com.mzm.chapter12;

/**
 * Created by 蒙卓明 on 2017/10/22.
 */
public class MultipleReturns {

    public static void f(int i){
        System.out.println("Initialization that requires cleanup");
        try{
            System.out.println("Point 1");
            if(i == 1){
                return;
            }
            System.out.println("Point 2");
            if(i == 2){
                return;
            }
            System.out.println("Point 3");
            if(i == 3){
                return;
            }
            System.out.println("End");
            return;
        } finally {
            System.out.println("Performing cleanup");
        }
    }

    public static void main(String[] args){
        for(int i = 1; i <= 4; i++){
            f(i);
        }
    }
}
12.8.3 缺憾:异常丢失

在某些情况下使用finally子句,可使异常被忽略。

package com.mzm.chapter12;

/**
 * 
 */
public class LostMessage {

    void f() throws VeryImportantException {
        throw new VeryImportantException();
    }

    void dispose() throws HoHumException {
        throw new HoHumException();
    }

    public static void main(String[] args) throws HoHumException {
        try{
            LostMessage lm = new LostMessage();
            try{
                lm.f();
            } finally {
                lm.dispose();
            }
        }catch (Exception e) {
            System.out.println(e);
        }
    }
}

class VeryImportantException extends Exception{
    public String toString(){
        return "A very important exception!";
    }
}

class HoHumException extends Exception{
    public String toString(){
        return "A trivial exception";
    }
}

VeryImportantException消失,其被finally子句中的HoHumException所取代。

package com.mzm.chapter12;

/**
 * 丢失异常
 * 
 */
public class ExceptionSilencer {

    public static void main(String[] args){
        try{
            throw new RuntimeException();
        } finally {
            //异常被忽略
            return;
        }
    }
}
12.9 异常的限制

当覆盖方法时,只能抛出在父类方法的异常说明中所列的异常,也可以不抛异常,只是不能抛出父类相应方法异常说明之外的异常。

针对构造器而言,子类的构造器的异常说明必须包含父类的构造器的异常说明,并且不能捕获父类构造器抛出的异常。

不能基于异常说明来重载方法。

12.10 构造器

在构造器中出现异常的情况,不要再finally子句中执行清理工作。

package com.mzm.chapter12;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * Created by 蒙卓明 on 2017/10/28.
 */
public class InputFile {

    private BufferedReader in;

    public InputFile(String fname) throws FileNotFoundException {
        try {
            in = new BufferedReader(new FileReader(fname));
        } catch (FileNotFoundException e) {
            System.out.println("Could not open " + fname);
            throw e;
        } catch (Exception e) {
            try{
                in.close();
            } catch (IOException e1) {
                System.out.println("in.close() unsuccessful");
            }

            throw e;
        } finally {
            //不建议在此处执行清理工作,因为文件未成功打开
        }
    }

    /**
     * 获取文件的下一行
     * @return 文件的下一行内容的字符串
     */
    public String getLine() {
        String s;
        try{
            s = in.readLine();
        } catch (IOException e) {
            throw new RuntimeException("readLine() failed");
        }
        return s;
    }

    public void dispose() {
        try{
            in.close();
            System.out.println("dispose() successful");
        } catch (IOException e) {
            throw new RuntimeException("in.close() failed");
        }
    }
}
12.11 异常匹配

抛出异常时,异常系统会按照就近原则找出最近的处理程序。原则上再编写代码时,子异常类在前,父异常类在后。

12.12 其他可选方式

开发异常程序的初衷是为了方便程序员处理错误。
异常处理的重要原则:只有在知道如何处理的情况下才捕获异常。
异常处理的目标:将异常发生地点与异常处理代码分离。

12.12.3 把异常传递给控制台

即在main()方法上加上异常说明,但是此种方式不推荐。

12.12.4 把”被检查的异常”转换为”不检查的异常”

实际上就是异常转型,将编译时异常转型成为运行时异常。

try {
    // ... to do somrthing useful
} catch (IDontKonwWhatToDoWithThisCheckedException e) {
    throw new RuntimeException(e);
}
12.13 异常使用指南

1) 在知道如何处理的情况下才捕获异常;
2) 解决问题并且重新调用产生异常的方法;
3) 进行少许修补,然后绕过异常发生的地方继续执行;
4) 用别的数据进行计算,以代替方法预计会返回的值;
5) 把当前运行环境下能做的事情尽量做完,然后把相同的异常抛到更高层;
6) 把当前运行环境下能做的事情尽量做完,然后把不同的异常抛到更高层;
7) 终止程序;
8) 进行简化;
9) 让类库和程序更安全。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值