一、抛出、捕获异常
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高兴地接走了狗。