try-catch-finally 是对Java异常的处理;如果异常不处理,Java程序会执行到异常代码处(执行时异常)结束程序执行;如果希望异常代码之后的代码也能正常输入,那么必须对异常进行处理,try-catch-finally 就是其中一种方法;这里我们以对执行时异常的处理为例;
public class Test{
public static void main(String[] args) {
System.out.println(1/0);
System.out.println(1/1);
}
}
执行这个代码,我们会发现代码直接报错,而其后能正常执行的 System.out.println(1/1); 没有执行,这就是我们所说的,程序执行到异常代码时,会直接结束程序,其后代码不再执行,如果需要其后的代码正常执行,那就需要我们对异常进行处理;
public class Test{
public static void main(String[] args) {
try {
System.out.println(1 / 0);
} catch (ArithmeticException e) {
System.out.println(e);
}
System.out.println(1/1);
}
}
java.lang.ArithmeticException: / by zero
1
这个代码执行后,我们就会发现,对程序进行处理后就不再影响后续代码的执行了;
public class Test{
public static void main(String[] args) {
try {
System.out.println(1 / 0);
} catch (ArithmeticException e) {
System.out.println("算数错误异常,0不能做分母"+e);
}catch(RuntimeException e){
System.out.println("运行时异常"+e);
}catch(Exception e) {
System.out.println("出现异常"+e);
}
System.out.println(1/1);
}
}
算数错误异常,0不能做分母java.lang.ArithmeticException: / by zero
1
然后我们看多个 catch 分支语句(执行顺序同if else);当我们不是很确定异常具体属于哪种异常,我们可以使用 catch 多分支语句进行判断,但是要注意:catch 多分支语句捕获异常时要从小到大,即从子类到父类捕获异常,不可颠倒,在不这里不再举例,可自行探索。(这里 Exception 是 RuntimeException 的父类,而 RuntimeException 又是 ArithmeticException 的父类)
catch 多个分支异常处理时注意:程序执行期间出现哪个异常就由哪个异常语句处理,若有 Exception 分支,则 try 语句中出现的其他异常均由该语句处理。
1 public class Test{
2 public static void main(String[] args) {
3 try {
4 System.out.println(1 / 0);
5 String name = null;
6 System.out .println(name.length());
7 } catch (ArithmeticException e) {
8 System.out.println("算数错误异常,0不能做分母"+e);
9 }catch(NullPointerException e) {
10 System.out.println("尝试访问null对象成员异常"+e);
11 }catch(RuntimeException e){
12 System.out.println("运行时异常"+e);
13 }catch(Exception e) {
14 System.out.println("出现异常"+e);
15 }
16 System.out.println(1/1);
17 }
18 }
算数错误异常,0不能做分母java.lang.ArithmeticException: / by zero
1
我们再看这个例子,虽然有两种异常。但是执行程序只处理了一种异常,这就是涉及到了一个 try-catch 结构只能处理一个异常,若果多个异常并行出现,那么 try-catch 只会处理第一个异常而忽略其余异常,想要逐一处理,则只能使用多个 try-catch 结构;如下:
public class Test{
public static void main(String[] args) {
try {
System.out.println(1 / 0);
} catch (ArithmeticException e) {
System.out.println("算数错误异常,0不能做分母"+e);
}
try{
String name = null;
System.out .println(name.length());
}catch(NullPointerException e) {
System.out.println("尝试访问null对象成员异常"+e);
}
}
}
算数错误异常,0不能做分母java.lang.ArithmeticException: / by zero
尝试访问null对象成员异常java.lang.NullPointerException
上文中我们说过,程序一旦遇到没有执行处理的异常就会结束掉程序,而前面多行异常,除第一行处理了外其他都没处理,为什么程序没有终止,依旧执行完了;原因就是 try-catch 只能处理一个异常,发现异常会直接进入异常捕获阶段,进行异常处理,也就是和要被 try-catch 处理的那个异常处于并行的其他异常并没有执行的机会,会直接跳过,但因为是运行时异常,Java在编译时没有发现那些代码不会被执行,所以也就没有报错。
public class Test{
public static void main(String[] args) {
try {
System.out.println(1 / 0); //注意
} catch (ArithmeticException e) {
System.out.println("算数错误异常,0不能做分母"+e);
}finally {
System.out.println("This is OK");
}
System.out.println(1/1);
}
}
算数错误异常,0不能做分母java.lang.ArithmeticException: / by zero
This is OK
1
public class Test{
public static void main(String[] args) {
try {
System.out.println(1 / 1); //注意变化
} catch (ArithmeticException e) {
System.out.println("算数错误异常,0不能做分母"+e);
}finally {
System.out.println("This is OK");
}
System.out.println(1/1);
}
}
1
This is OK
1
在 try-catch 语句块中加入finally 语句,可以确保无论异常有没有发生, finally 语句块中的代码总会执行。
注意:try-catch 语句块中 finally 语句总会执行,就算 try-catch-finally 语句块中在方法中,而方法中有 return ;或者有返回值,finally 语句块依旧会在方法结束之前执行。
public class TestException {
public static void main(String[] args) {
try {
String[] nameArray = { "小王", "小李", "小高" };
for (int i = 0; i < 4; i++) {
System.out.println(nameArray[i]);
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数据下标越界,请修改程序!");
System.out.println("调用异常对象的getMessage()方法:");
System.out.println(e.getMessage());
System.out.println("调用异常对象的printStackTrace()方法:");
e.printStackTrace();
return;// finally语句块仍然执行
// System.exit(1);//直接退出JVM,finally语句块不再执行
} finally {
System.out.println("显示完毕!");
}
System.out.println("显示完毕!");
}
}
小高
java.lang.ArrayIndexOutOfBoundsException: 3
at p1.TestException.main(TestException.java:9)
数据下标越界,请修改程序!
调用异常对象的getMessage()方法:
3
调用异常对象的printStackTrace()方法:
显示完毕!
当然如果是 exit 强行退出,则 finally 语句块不会执行。