Java try catch异常处理详解(通俗易懂,新手必看)
Java 通过 3 个关键字来控制异常处理。通常在出现错误时用 try 执行代码,系统引发(throws)一个异常后,可以根据异常的类型由 catch 捕获,或者用 finally 调用默认异常处理。
为了防止和处理运行时错误,把要监控的代码放进 try 语句块中就可以了。在 try 语句块后,可以包括一个或多个程序员希望捕获的错误类型的 catch 子句,具体语法格式如下:
在上面的程序代码中,对可能会出现错误的代码用 try…catch 语句进行了处理。当 try 代码块中的语句发生了异常,程序就会跳转到 catch 代码块中执行,执行完 catch 代码块中的程序代码后,系统会继续执行 catch 代码块后的其他代码,但不会执行 try 代码块中发生异常语句后的代码。
当 try 代码块中的程序发生了异常,系统将这个异常发生的代码行号、类别等信息封装到一个对象中,并将这个对象传递给 catch 代码块。catch 代码块是以下面的格式出现的:
catch 语句可以有多个,分别处理不同类型的异常。Java 运行时系统从上到下分别对每个 catch 语句处理的异常类型进行检测,直到找到类型相匹配的 catch 语句为止。这里,类型匹配是指 catch 所处理的异常类型与生成的异常对象的类型完全一致或者是它的父类。因此,catch 语句的排列顺序应该是从特殊到一般。
用一个 catch 语句也可以处理多个异常类型,这时它的参数应该是多个异常类型的父类。在程序设计过程中,要根据具体的情况选择 catch 语句的异常处理类型。下面通过例子来说明。
【实例】使用多个 catch 捕获可能产生的多个异常。
如果调换一下语句的顺序,变成如下实例中的程序,则程序的执行结果就会发生变化:
如果不能确定程序中到底会发生何种异常,那么可以不用明确地抛出那种异常,而直接使用 Exception 类。因为它是所有异常类的超类,所以任何类型的异常都会和 Exception 类匹配,也就会被捕获。如果想知道究竟发生了何种异常,可以通过向控制台输出信息来判断,使用 toString() 方法,可以输出具体异常信息的描述。
但是,在使用 Exception 类时需要注意,当使用多个 catch 语句时,必须把其他需要明确捕获的异常类放在 Exception 类之前,否则编译时会报错。因为 Exception 类是诸如 ArithmeticException 类的父类,而应用父类的 catch 语句将捕获该类型及其所有子类类型异常,如果子类异常在其父类后面,子类异常所在位置将永远不会到达。
无论 try 代码块是否抛出异常,finally 代码块都要被执行。它提供统一的出口,可以把一些善后的工作放在 finally 代码块中,例如关闭打开的文件、数据库和网络连接等。
【实例】使用 finally 语句进行善后处理。
如果没有 catch 语句匹配,Java 运行时环境将自动处理这个异常。如果在一个 try 块中有可能产生多个异常,那么当第一个异常被捕获后,后续的代码不会被执行,则其他异常也不能产生。为了执行 try 块所有的代码,捕获所有可能产生的异常,可以使用嵌套的 try 语句。
【实例】使用嵌套的 try 语句捕获程序中产生的所有异常。
为了防止和处理运行时错误,把要监控的代码放进 try 语句块中就可以了。在 try 语句块后,可以包括一个或多个程序员希望捕获的错误类型的 catch 子句,具体语法格式如下:
try{ ....// 执行代码块 }catch (ExceptionType1 e1) { ....// 对异常类型 1 的处理 }catch (ExceptionType2 e2) { ....// 对异常类型 2 的处理 } finally{ ... }
Java try和catch语句
先看一个实例:public class ExceptionHaveCatch { public static void main(String[] args) { int i = 0; String greetings [] = { "Hello world!", "No, I mean it!", "HELLO WORLD!!!" }; try{ while (i < 4) { System.out.println(greetings[i]); i++; } }catch(Exception ex) { System.out.println("捕捉异常信息!"); ex.printStackTrace(); // 获取异常信息 } } }程序执行结果为:
Hello world! No, I mean it! HELLO WORLD!!! 捕捉异常信息! java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at ExceptionHaveCatch.main(ExceptionHaveCatch.java:11)可见程序在出现异常后,系统能够正常地继续运行,没有异常终止。
在上面的程序代码中,对可能会出现错误的代码用 try…catch 语句进行了处理。当 try 代码块中的语句发生了异常,程序就会跳转到 catch 代码块中执行,执行完 catch 代码块中的程序代码后,系统会继续执行 catch 代码块后的其他代码,但不会执行 try 代码块中发生异常语句后的代码。
当 try 代码块中的程序发生了异常,系统将这个异常发生的代码行号、类别等信息封装到一个对象中,并将这个对象传递给 catch 代码块。catch 代码块是以下面的格式出现的:
catch (Exception ex) { ex.printStackTrace(); }catch 关键字后面括号中的 Exception 就是 try 代码块传递给 catch 代码块的变量类型,ex 是变量名。
catch 语句可以有多个,分别处理不同类型的异常。Java 运行时系统从上到下分别对每个 catch 语句处理的异常类型进行检测,直到找到类型相匹配的 catch 语句为止。这里,类型匹配是指 catch 所处理的异常类型与生成的异常对象的类型完全一致或者是它的父类。因此,catch 语句的排列顺序应该是从特殊到一般。
用一个 catch 语句也可以处理多个异常类型,这时它的参数应该是多个异常类型的父类。在程序设计过程中,要根据具体的情况选择 catch 语句的异常处理类型。下面通过例子来说明。
【实例】使用多个 catch 捕获可能产生的多个异常。
public class MutiCatchFirstDemo { public static void main(String[] args) { String friends[]={"Kelly","Sandy","Jeck","Chery"}; try{// 此语句段内可能会产生两类异常 for(int i=0;i<=4;i++)// 访问数组中的元素,可能产生数组越界异常 System.out.println(friends[i]); int num=friends.length/0; // 进行除法运算,产生除数为 0 异常 }catch(ArrayIndexOutOfBoundsException e){ // 先捕获数组越界异常 e.printStackTrace(); }catch(ArithmeticException e){ // 接着捕获数学异常 e.printStackTrace(); } } }程序执行结果为:
Kelly Sandy Jeck Chery java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4 at MutiCatchFirstDemo.main(MutiCatchFirstDemo.java:6)从运行结果可以看出,ArrayIndexOutOfBoundsException 异常类型的对象被捕获,而 ArithmeticException 异常类型的对象没有被捕获。这是因为首先执行 for 循环,当执行到 i 变为 4 的时候,访问 friend[4] 时发生了数组下标越界异常,和第一个 catch 后面的异常匹配,就直接跳出 try 语句,所以后面除 0 的语句不会被执行,也就不会发生 ArithmeticException 异常。
如果调换一下语句的顺序,变成如下实例中的程序,则程序的执行结果就会发生变化:
public class MutiCatchSecondDemo { public static void main(String[] args) { String friends[]={"Kelly","Sandy","Jeck","Chery"}; try{ // 首先进行除法运算,产生除数为 0 异常 int num=friends.length/0; // 接着访问数组中的元素,可能产生数组越界异常 for(int i=0;i<=4;i++) System.out.println(friends[i]); }catch(ArrayIndexOutOfBoundsException e) { e.printStackTrace(); }catch(ArithmeticException e) { e.printStackTrace(); } } }程序执行结果为:
java.lang.ArithmeticException: / by zero at MutiCatchSecondDemo.main(MutiCatchSecondDemo.java:6)ArithmeticException 异常类的对象被捕获,而 ArrayIndexOutOf-BoundsException 异常类的对象没有被捕获。
如果不能确定程序中到底会发生何种异常,那么可以不用明确地抛出那种异常,而直接使用 Exception 类。因为它是所有异常类的超类,所以任何类型的异常都会和 Exception 类匹配,也就会被捕获。如果想知道究竟发生了何种异常,可以通过向控制台输出信息来判断,使用 toString() 方法,可以输出具体异常信息的描述。
但是,在使用 Exception 类时需要注意,当使用多个 catch 语句时,必须把其他需要明确捕获的异常类放在 Exception 类之前,否则编译时会报错。因为 Exception 类是诸如 ArithmeticException 类的父类,而应用父类的 catch 语句将捕获该类型及其所有子类类型异常,如果子类异常在其父类后面,子类异常所在位置将永远不会到达。
Java finally语句
try 块中的代码,当执行到某一条语句抛出了一个异常时,其后的代码不会被执行。但是在异常发生后,往往需要做一些善后处理,此时可以使用 finally 语句。无论 try 代码块是否抛出异常,finally 代码块都要被执行。它提供统一的出口,可以把一些善后的工作放在 finally 代码块中,例如关闭打开的文件、数据库和网络连接等。
【实例】使用 finally 语句进行善后处理。
public class TestFinally { public static void main(String args[]) { int i = 0; String greetings[] = { "Hello", "How are you", "Nice to meet you" }; try { while (i < 4) { // 特别注意循环控制变量 i 的设计,避免造成无限循环 System.out.println(greetings[i++]); } }catch (ArrayIndexOutOfBoundsException e) { System.out.println("数组下标越界异常 "); } finally{ System.out.println("执行 finally 代码块 "); } } }程序执行结果为:
Hello
How are you
Nice to meet you
数组下标越界异常
执行 finally 代码块
Java try语句的嵌套
try 语句可以被嵌套。在嵌套的时候,try 语句块可以位于另一个 try 语句块的内部。每次进入 try 语句块,异常的前后关系都会被推入某一个堆栈。如果内部的 try 语句不含特殊异常 catch 处理程序,堆栈将弹出,由下一个 try 语句的 catch 处理程序检查是否与之匹配。这个过程将继续下去,直到 catch 语句匹配成功,或者是直到所有的嵌套 try 语句被检查耗尽。如果没有 catch 语句匹配,Java 运行时环境将自动处理这个异常。如果在一个 try 块中有可能产生多个异常,那么当第一个异常被捕获后,后续的代码不会被执行,则其他异常也不能产生。为了执行 try 块所有的代码,捕获所有可能产生的异常,可以使用嵌套的 try 语句。
【实例】使用嵌套的 try 语句捕获程序中产生的所有异常。
public class NestedTryDemo { public static void main(String[] args) { String friends[]={"Kelly","Sandy","Jeck","Chery"}; try{ try{ // 先捕获除数为 0 的异常 int num=friends.length/0; }catch(ArithmeticException e){ e.printStackTrace(); } // 即使发生了 ArithmeticException 异常,也会被执行 for(int i=0;i<=4;i++) System.out.println(friends[i]); }catch(ArrayIndexOutOfBoundsException e){ // 捕获数组越界异常 e.printStackTrace(); } } }程序执行结果为:
java.lang.ArithmeticException: / by zero at NestedTryDemo.main(NestedTryDemo.java:7) Kelly Sandy Jeck Chery java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4 at NestedTryDemo.main(NestedTryDemo.java:13)