Week 5.3 | Lecture 14 | Exception | CS61B-Spring-2018

本文介绍了Java中的异常处理机制,包括如何抛出和捕获异常,以及checked和unchecked异常的区别。通过具体的try-catch例子,解释了如何在遇到错误时保持程序的运行,并提供了对checked异常的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、抛出、捕获异常

1. Throw exception

  • 隐式异常:Java本身抛出的异常。
public static void main (String[] args) {
    ArrayMap<String, Integer> am = new ArrayMap<String, Integer>();
    am.put("hello", 5);
    System.out.println(am.get("yolp"));
}
$ java ExceptionDemo
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at ArrayMap.get(ArrayMap.java:38)
at ExceptionDemo.main(ExceptionDemo.java:6)
  • 显式异常:作为程序员,我们可以使用throw关键字抛出自己的异常。这使我们能够提供我们自己的错误消息,这些错误消息可能对用户更有帮助。我们还可以为程序中的错误处理代码提供信息。
public V get(K key) {
    int location = findKey(key);
if(location < 0) {
    throw new IllegalArgumentException("Key " + key + " does not exist in map."\); 
}
    return values[findKey(key)];
}
$java ExceptionDemo
Exception in thread "main" java.lang.IllegalArgumentException: Key yolp does not exist in map.
at ArrayMap.get(ArrayMap.java:40)
at ExceptionDemo.main(ExceptionDemo.java:6)

new IllegalArgumentException("…")就相当于实例化了一个IllegalArgumentException对象。

2. Catch exception

throw exception会让整个程序停止运行。
而try and catch能够保护程序继续运行,防止它被停止,甚至可以采取补救方法。

所以最重要的是:它们使错误处理在概念上与程序的其余部分分开。

Eg.
打开文件可能有很多错误,比如文件不存在,赋值超出size,内存不够等等。我们首先要做与读取文件有关的所有事情,并将它们包装在try语句中。然后,如果在该操作序列中的任何位置发生错误,它将被适当的catch语句捕获。我们可以为每种类型的异常提供不同的补救措施,确保文件正常打开。

func readFile: {
    try {
        open the file;
        determine its size;
        allocate that much memory;
        read the file into memory;
        close the file;
    } catch (fileOpenFailed) {
        doSomething;
    } catch (sizeDeterminationFailed) {
        doSomething;
    } catch (memoryAllocationFailed) {
        doSomething;
    } catch (readFailed) {
        doSomething;    
    } catch (fileCloseFailed) {
        doSomething;
    }
}

3. 未被捕获的异常

当程序运行发现了一个错误,它会沿着call stack向下寻找catch语句,如果直到main也没有找到catch语句,程序就停止运行。
在这里插入图片描述
Java为用户提供一条消息,打印出堆栈跟踪。

java.lang.RuntimeException in thread “main”: 
at ArrayRingBuffer.peek:63 
at GuitarString.sample:48 
at GuitarHeroLite.java:110

二、checked and unchecked exceptions

在这里插入图片描述
unchecked:运行时才能知道的错误。
checked:编译器能够检查出来的错误。在运行之前必须改正,也是为了保护程序运行。

1. unchecked exception

public class UncheckedExceptionDemo {
    public static void main(String[] args) {
        if (today == “Thursday”) { 
            throw new RuntimeException("as a joke"); 
        }    
    }
}

运行时才报错:

$ javac UncheckedExceptionDemo.java
$ java UncheckedExceptionDemo
Exception in thread "main" java.lang.RuntimeException: as a joke.
at UncheckedExceptionDemo.main(UncheckedExceptionDemo.java:3)

可以用try and catch处理,防止程序崩溃。

2. checked exception

public class Eagle {
    public static void gulgate() {
        if (today == “Thursday”) { 
            throw new IOException("hi"); }
        }
    }

编译时就会报错:(以下是命令行编译结果,如果是IDEA的话直接红色波浪线)

$ javac Eagle
Eagle.java:4: error: unreported exception IOException; must be caught or declared to be thrown
throw new IOException("hi"); }
^

因为编译器自动会检查IOException,发现程序中有checked exception,所以报错,不能运行。正常情况下check errors必须修改完之后才能运行。但也有特殊方法让在有checked exception时也能运行,见下一部分。

3. checked exception的处理方法

为了让程序能够编译,有两种办法:

  • catch:直接在发现exception的时候对其捕获并进行修正。
public static void gulgate() {
    try {
        if (today == “Thursday”) { 
            throw new IOException("hi"); 
        }
    } catch (Exception e) {
        System.out.println("psych!");
    }
}
  • specify:将其指定为危险方法,让错误逃逸。在这个方法中让错误逃逸,exception就被转移到上一层方法,上一层方法也有catch和specify两种方法处理exception。可以在其上一层方法(即调用它的地方)对其进行catch与修正。如果上一层方法也无法修正,可以让上一层方法也throws IOException,让错误逃掉。如果最终连main函数也无法修正,也可以指定main函数throws IOException。
public static void gulgate() throws IOException {
... throw new IOException("hi"); ...
}

要么让main修正:

public static void main(String[] args) {
    try {
        gulgate();
    } catch(IOException e) {
        System.out.println("Averted!");
    }
}

要么让main函数指定:

public static void main(String[] args) throws IOException {
    gulgate();
}

附录:一个try and catch的小例子

没啥用,可以参考

  • 保护程序继续执行
Dog d = new Dog("Lucy", "Retriever", 80); 
d.becomeAngry();  狗生气了
try {
    d.receivePat();  尝试把狗送给lucy
} catch (Exception e) {   送的时候捕捉错误
    System.out.println("Tried to pat: " + e);  打印拍打安抚狗
}
System.out.println(d);  打印狗的状态
$ java ExceptionDemo
Tried to pat: java.lang.RuntimeException: grrr... snarl snarl
Lucy is a displeased Retriever weighing 80.0 standard lb units.

lucy不高兴了。虽然捕捉到了错误,可是狗还是送走了。

  • 补救措施
Dog d = new Dog("Lucy", "Retriever", 80);
d.becomeAngry();
try {
    d.receivePat();
} catch (Exception e) {
    System.out.println(
    "Tried to pat: " + e);
    d.eatTreat("banana"); 让狗吃香蕉
} 
d.receivePat(); 再送狗
System.out.println(d); 
$ java ExceptionDemo
Tried to pat: java.lang.RuntimeException: grrr... snarl snarl
Lucy munches the banana

Lucy enjoys the pat.

Lucy is a happy Retriever weighing 80.0 standard lb units.

lucy高兴地接走了狗。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值