异常
传递异常
注意:受查异常必须要声明。受查异常包括IOException 及其子类。
public void read(String filename) throws IOException
{
...;
}捕捉异常
public void read(String filename)
{
try{
}catch(IOException exception){
...;
}
}通常, 应该捕获那些知道如何处理的异常, 而将那些不知道怎样处理的异常继续进行传递(传递给用户,让用户去操心)。
注意:不允许在子类的 throws 说明符中出现超过超类方法所列出的异常类范围。
当在try和catch语句外抛出异常,程序会终止。
public class Hello {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = new int[10];
int i = -1;
if (i < 0)
throw new ArrayIndexOutOfBoundsException();
//此时程序会终止并抛出一个异常,不会被后面或者上层代码捕捉
try {
arr[i] = -1;
} catch (RuntimeException a) {
System.out.println("OK");
//will not print
}
}
}在try语句中抛出异常,继续执行catch子句及之后的代码。
public class Hello {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
int[] a = new int[10];
try {
throw new ArrayIndexOutOfBoundsException();
} catch (Exception e) {
System.out.println("OK");
}
System.out.println("YES");
}
}
//will print OK,YES在catch语句中抛出异常,异常会被抛回到这个方法的调用者或者外层代码。
捕捉多个异常
try{
}catch(...){
}catch(...){
}catch(...){
}...更简洁的形式:
try{
}catch(FileNotFoundException | UnknownHostException e)只有当捕获的异常类型彼此之间不存在子类关系时才需要这个特性。
再次抛出异常与异常链
如果 catch 子句抛出了一个异常, 异常将被抛回这个方法的调用者。
使用以下写法可以将底层代码出现的异常抛出给上层,然后抛出一个统一的代码,同时不会丢失最原始的异常信息。
建议使用
public class Hello {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = new int[10];
try {
try {
arr[-1] = -1;
} catch (ArrayIndexOutOfBoundsException a) {
RuntimeException b = new RuntimeException();
b.initCause(a);
throw b;
}
} catch (RuntimeException a) {
System.out.println(a.getCause());
}
}
}finally子句
不管是否有异常被捕获,finally 子句中的代码都被执行。
InputStream in = . .
try{
//code that might throwexceptions
}
finally
{
in.close();
}
//无论在 try 语句块中是否遇到异常,finally 子句中的 in.close() 语句都会被执行。在需要关闭资源时, 用这种方式使用 finally 子句是一种不错的选择。
强烈建议解搞合 try/catch 和 try/finally 语句块。这样可以提高代码的清晰度。
例如:
InputStrean in = . . .;
try{
try{
//code that might throwexceptions
}
finally{
in.close();
}
}
catch (IOException e){
show error message
}
//这样写,不仅清楚,而且还可以报告finally子句中出现的错误。当 finally 子句包含 return 语句时,执行后会覆盖原来原来返回的值。
public class Hello {
public static int f(int n) {
try {
int r = n * n;
return r;
} finally {
if (n == 2)
return 0;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(f(2));
//will print 0
}
}带资源的try语句
try (Resource res = . . .)
{
work with res
}
try块退出时,会自动调用 res.close()。
断言
断言机制允许在测试期间向代码中插入一些检査语句。当代码发布时,这些插人的检测 语句将会被自动地移走。
什么时候应该选择使用断言呢? 请记住下面几点:
断言失败是致命的、 不可恢复的错误。
断言检查只用于开发和测阶段(这种做法有时候被戏称为“ 在靠近海岸时穿上救生衣, 但在海中央时就把救生衣抛掉吧”)。
因此,不应该使用断言向程序的其他部分通告发生了可恢复性的错误,或者,不应该作 为程序向用户通告问题的手段。断言只应该用于在测试阶段确定程序内部的错误位置;
assert 条件; assert 条件:表达式; //结果为false时抛出一个AssertionError异常,表达式将被传入AssertionError构造器,并转换成一个消息字符串