1.异常处理方法
一个健壮的程序必须处理各种各样的错误,所谓错误,就是程序调用某个函数的时候,如果失败了,就表示出错。
调用方获知调用失败的信息有两种方法:
方法一:约定返回错误码。(不常用)
举例:处理一个文件,如果返回0
,表示成功,返回其他整数,表示约定的错误码:
int code = processFile("C:\\test.txt");
if (code == 0) {
// ok:
} else {
// error:
switch (code) {
case 1:
// file not found:
case 2:
// no read permission:
default:
// unknown error:
}
}
因为使用int
类型的错误码,想要处理就非常麻烦。这种方式常见于底层C函数。
方法二:异常处理机制。
Java内置了一套异常处理机制,总是使用异常来表示错误。
举例:
try {
String s = processFile(“C:\\test.txt”);
// ok:
} catch (FileNotFoundException e) {
// file not found:
} catch (SecurityException e) {
// no read permission:
} catch (IOException e) {
// io error:
} catch (Exception e) {
// other error:
}
Error
是无需捕获的严重错误,Exception
是应该捕获的可处理的错误;
Java规定:
必须捕获的异常,包括Exception
及其子类,但不包括RuntimeException
及其子类,这种类型的异常称为Checked Exception。不需要捕获的异常,包括Error
及其子类,RuntimeException
及其子类。
2.异常捕获
捕获异常使用try...catch
语句,把可能发生异常的代码放到try {...}
中,然后使用catch
捕获对应的Exception
及其子类:
public class Main {
public static void main(String[] args) {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
}
static byte[] toGBK(String s) {
try {
// 用指定编码转换String为byte[]:
return s.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
// 如果系统不支持GBK编码,会捕获到UnsupportedEncodingException:
System.out.println(e); // 打印异常信息
return s.getBytes(); // 尝试使用用默认编码
}
}
}
2.1多catch语句
可以使用多个catch
语句,每个catch
分别捕获对应的Exception
及其子类。JVM在捕获到异常后,会从上到下匹配catch
语句,匹配到某个catch
后,执行catch
代码块,然后不再继续匹配。
存在多个catch
的时候,catch
的顺序非常重要:子类必须写在前面。例如:
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (IOException e) {
System.out.println("IO error");
} catch (UnsupportedEncodingException e) { // 永远捕获不到
System.out.println("Bad encoding");
}
}
对于上面的代码,UnsupportedEncodingException
异常是永远捕获不到的,因为它是IOException
的子类。当抛出UnsupportedEncodingException
异常时,会被catch (IOException e) { ... }
捕获并执行。
因此,正确的写法是把子类放到前面:
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (UnsupportedEncodingException e) {
System.out.println("Bad encoding");
} catch (IOException e) {
System.out.println("IO error");
}
}
2.2 finally语句
Java的try ... catch
机制还提供了finally
语句,finally
语句块保证有无错误都会执行。上述代码可以改写如下:
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (UnsupportedEncodingException e) {
System.out.println("Bad encoding");
} catch (IOException e) {
System.out.println("IO error");
} finally {
System.out.println("END");
}
}
finally语句的特点:
(1)finally语句不是必须的,可写可不写。
(2)finally总是最后才执行。
2.3捕获多种异常
如果某些异常的处理逻辑相同,但是异常本身不存在继承关系,那么就得编写多条catch
子句:
public static void main(String[] args) {
try {
process1();
process2();
process3();
} catch (IOException | NumberFormatException e) { // IOException或NumberFormatException
System.out.println("Bad input");
} catch (Exception e) {
System.out.println("Unknown error");
}
}