当前位置:  首页>> 技术小册>> Java语言基础7-Java中的异常

5.1 异常处理的方式

  • ① try..catch..finally 。
  • ② throw 和 throws 。

5.2 异常 throw

  • Java 程序的执行过程中如果出现了异常,会产生一个 异常类对象 ,该异常对象将被提交给 JVM ,这个过程称为 抛出异常 。
  • 异常对象的生成:
    • ① 由 JVM 自动生成 :程序运行结果中,JVM 检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应的异常类的实例对象并抛出(自动抛出)。
    • ② 由开发人员 手动抛出 :由开发人员通过 throw new Exception对象 或 throw new Exception的子类对象 手动抛出异常。
  • 手动抛出异常的场景:在定义方法的时候,方法需要接收参数,当调用方法使用接收到的参数的时候,需要先对参数数据进行合法性的校验,数据如果不合法,就应该告诉调用者,这时我们可以通过抛出异常的方式来告诉调用者。
  • 在 Java 中,提供了一个 throw 的关键字,它用来抛出一个指定的异常的对象。
  • 手动抛出异常的步骤:
    • ① 创建一个异常对象。
    • ② 通过 throw new 异常对象 ,将异常告诉给调用者。
      注意:
  • throw 关键字必须用在方法内,它用来抛出一个异常对象,将这个异常传递给方法的调用者,并结束当前方法的执行。
  • 方法的调用者要么进行异常捕获处理,要么使用 throws 声明处理,当然也可以通过 throw 关键字继续抛出异常。

  • 语法:

  1. thorw new 异常类名(实参);

示例:

  1. package com.github.demo2;
  2. /**
  3. *
  4. * @author maxiaoke.com
  5. * @version 1.0
  6. * @return
  7. */
  8. public class TestException {
  9. public static void main(String[] args) {
  10. int[] arr = {1, 2, 3};
  11. int element = getElement(arr, 2);
  12. System.out.println("element = " + element);
  13. /**
  14. Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 数组索引越界
  15. at com.github.demo2.TestException.getElement(TestException.java:27)
  16. at com.github.demo2.TestException.main(TestException.java:16)
  17. */
  18. int e = getElement(arr, 3);
  19. System.out.println("e = " + e);
  20. System.out.println("main方法结束");
  21. }
  22. public static int getElement(int[] arr, int index) {
  23. if (null == arr) {
  24. throw new NullPointerException("要访问的arr数组不存在");
  25. }
  26. if (index < 0 || index > arr.length - 1) {
  27. throw new ArrayIndexOutOfBoundsException("数组索引越界");
  28. }
  29. return arr[index];
  30. }
  31. }

5.3 声明异常 throws
声明异常 :将异常标识出来,告诉调用者。如果方法内通过 throw 关键字 编译时异常(非runtime异常) ,而没有捕获处理,那么必须通过throws 进行声明,让调用者进行处理。
关键字 throws 用在方法声明上,告诉调用者当前方法不处理异常,而是提醒该方法的调用者来处理异常。

语法:

  1. 修饰符 返回值类型 方法名(形参列表) throws 异常类名1,异常类名2...{}

示例:

  1. package com.github.demo3;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. /**
  5. * @author maxiaoke.com
  6. * @version 1.0
  7. * @return
  8. */
  9. public class TestException {
  10. public static void main(String[] args) throws FileNotFoundException {
  11. readFile("java秘籍");
  12. }
  13. public static void readFile(String filePath) throws FileNotFoundException {
  14. File file = new File(filePath);
  15. if (!file.exists()) {
  16. throw new FileNotFoundException(filePath + "文件不存在");
  17. }
  18. }
  19. }

5.4 try…catch…finally
如果一个方法内没有抛出异常,该异常对象会被抛出给调用者方法中处理。如果异常没有在调用者方法中处理,它会继续抛给这个调用方法的上层方法。这个过程将一直继续下去,直到异常被处理,这个过程称为 捕获异常 。

如果一个异常回到 main 方法处,并且 main 方法也不处理,则程序终止运行。

语法:

  1. try{
  2. ...... //可能产生异常的代码 }
  3. catch( ExceptionName1 e ){
  4. ...... //当产生ExceptionName1型异常时的处置措施 }
  5. catch( ExceptionName2 e ){
  6. ...... //当产生ExceptionName2型异常时的处置措施 }
  7. finally{
  8. ...... //无论是否发生异常,都无条件执行的语句
  9. }
  • 解释:

    • try :捕获异常的第一步是用 try{} 语句块选定捕获异常的范围,将可能出现异常的代码放到 try 语句块中。
    • catch(Exception e) :
      • 在 catch 语句块中是对 异常对象 进行处理的代码。每个 try 语句块可以伴随 一个或多个catch 语句,用于处理可能产生的 不同类型 的异常对象。
      • 如果明确知道产生的是何种异常,可以用该异常类作为 catch 的参数,也可以用其父类作为 catch 的参数。
      • 多个 catch 语句块,子类型在上,父类型在下。
    • finally :
      • 捕获异常的最后一步是通过 finally 语句为异常处理提供一个统一的出口,使得在程序流程到其它部分以后,能够对程序的状态做出统一的处理。
      • 不论在try代码块中是否发生了异常,catch语句中是否执行,catch语句中是否有异常,catch语句中是否有return,finally块中的语句都会被执行。
        注意:当在 try 或者 catch 中调用退出 JVM 的相关方法,例如 System.exit(0) ,此时 finally 不会执行,否则 finally 永远会执行。
  • 示例:

  1. package com.github.demo4;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. /**
  5. * @author maxiaoke.com
  6. * @version 1.0
  7. * @return
  8. */
  9. public class TestException {
  10. public static void main(String[] args) {
  11. readFile("不敲代码学会Java秘籍.txt");
  12. System.out.println("继续学习吧...");
  13. }
  14. public static void readFile(String filePath) {
  15. File file = new File(filePath);
  16. try {
  17. if (!file.exists()) {
  18. throw new FileNotFoundException(filePath + "文件不存在");
  19. }
  20. if (!file.isFile()) {
  21. throw new IllegalAccessException(filePath + "非法访问");
  22. }
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. } finally {
  26. System.out.println("这里的代码一定会执行");
  27. }
  28. }
  29. }

5.5 不捕获异常的情况
① 如果抛出的异常都是 Exception 或其子类型的运行时异常,这些运行时异常的特点是:即使没有使用 try 和 catch 捕获,Java 自己也能捕获,并且编译通过,但是运行的时候发生异常会使得程序终止运行。
② 如果抛出的异常都是 IOException 等类型的非运行异常,则 必须捕获,否则编译错误 。换言之,我们必须处理编译时异常,将这类类型的异常捕获,转换为运行时异常。

5.6 try … catch 新特性(JDK 1.7)
如果多个 catch 分支的异常处理代码一致的,在 JDK 1.7 之前是非常繁琐的。

  1. try {
  2. }catch (异常类型 e){
  3. // 处理异常的代码
  4. }catch (异常类型 e){
  5. // 处理异常的代码
  6. }

但是,在 JDK 1.7 的时候可以简化上述的代码。

  1. try {
  2. }catch (异常类型1 | 异常类型2 e){
  3. // 处理异常的代码
  4. }

示例:

  1. package com.github.day09;
  2. import java.util.Scanner;
  3. /**
  4. * @author maxiaoke.com
  5. * @version 1.0
  6. */
  7. public class TryCatchJDK7 {
  8. public static void main(String[] args) {
  9. Scanner input = new Scanner(System.in);
  10. try {
  11. System.out.print("请输入第一个整数:");
  12. int a = input.nextInt();
  13. System.out.print("请输入第二个整数:");
  14. int b = input.nextInt();
  15. int result = a / b;
  16. System.out.println("result = " + result);
  17. } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
  18. System.out.println("数字格式不正确,请输入两个整数");
  19. } catch (ArithmeticException e) {
  20. System.out.println("第二个整数不能为0");
  21. } catch (Exception e) {
  22. System.out.println("其他错误");
  23. }
  24. input.close();
  25. }
  26. }

该分类下的相关小册推荐: