找回密码
 立即注册
首页 业界区 安全 java 异常处理

java 异常处理

钱匾 2025-10-1 13:39:26
java 异常处理

1.异常体系

异常体系的顶级父类是 Throwable,这个类有两个子类:Error 和 Exception。
Throwable 听起来很像是一个接口,但是在 jdk17 中确实是一个类。


  • Error 类及其子类:通常指程序无法处理的严重问题,如系统错误或资源不足。
  • Exception 类及其子类:程序本身可以捕获和处理的异常,Exception 下面又可以分成两类:RuntimeException 和其他异常(编译时异常)。

    • RuntimeException:运行时异常,编译时不需要检查,只有程序实际运行起来才能发现,一般是因为代码逻辑错误引起的。
    • 其他异常:在 Exception 类下面除了 RuntimeException 就是其他异常,也叫做编译时异常,从语法角度讲是必须进行处理的异常,如果不处理,程序不能编译通过。

2.异常捕获

1.try catch

  • 若 try 中没有出现异常,则执行完 try 中的代码后跳过 catch,继续向下执行,会输出"pass..."
  • 若 try 中出现异常,则生成一个对应的异常对象并抛出,不再执行 try 下面的代码

    • 若 catch 能够捕获 try 中抛出的异常,则程序转入 catch 代码块中执行
    • 若 catch 没有捕获 try 中抛出的异常,则程序会将异常对象向上抛出,异常被传递到该方法的调用者进行处理

  • 在这里,由于 obj = null,所以"obj.toString()"会抛出空指针异常,不会再打印下面的"try..."。然后 catch 会尝试捕获这个空指针异常,空指针异常是运行时异常,所以空指针异常是 Exception 的子类,相当于 Exception e = new NullPointerException()。catch 捕获成功,执行"throw new RuntimeException(e)",由于这里又抛出了一个异常,但是没有其他 catch 进行捕获,所以下面不会再打印"pass..."。(如果 catch 中没有抛出异常,程序在执行完 catch 的代码后可以继续向下执行)
  • 注意:try catch 可以对异常进行处理,而且可以在出现异常后继续向下执行,在开发中需要特别注意。
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         try {
  4.             Object obj = null;
  5.             System.out.println(obj.toString()); // 空指针异常
  6.             System.out.println("try...");
  7.         } catch (Exception e) {
  8.             throw new RuntimeException(e);
  9.         }
  10.         System.out.println("pass...");
  11.     }
  12. }
复制代码
2.try catch finally
有了上面的基础,finally 就好理解多了,finally 表示必须要执行的代码:

  • 若 try 中没有出现异常,则 try --> finally --> 向下执行
  • 若 try 中出现异常,catch 尝试捕获异常

    • 若 catch 捕获成功,则 catch --> finally
    • 若 catch 捕获失败,则程序会在执行完 finally 中的代码后再停止

  • 即使在 try 或者 catch 中用 return 结束方法,finally 一样会执行。

    • 在 try 或者 catch 中 return 时,jvm 会使用一个变量保存要返回的值,即使后来在 finally 中再修改这个值,也能保证 return 的值不被修改。
    • 如果在 try 和 finally 中都有 return,此时会忽略 try,而执行 finally 的 return。

  1. public class Test {
  2.     public static void main(String[] args) {
  3.         try {
  4.             Object obj = null;
  5.             System.out.println(obj.toString()); // 空指针异常
  6.             System.out.println("try...");
  7.         } catch (Exception e) {
  8.             throw new RuntimeException(e); // catch成功并抛出另一个异常
  9.         } finally {
  10.             System.out.println("here is finally"); // 即使在catch中抛出一个新异常,finally一样会执行
  11.         }
  12.         System.out.println("pass..."); // 不会打印pass...
  13.     }
  14. }
  15. /////////////////////////////////////////////////////
  16. public class Test {
  17.     public static void main(String[] args) {
  18.         System.out.println(example());
  19.     }
  20.     public static int example() {
  21.         int i = 0;
  22.         try {
  23.             i++;
  24.             return i; // 1
  25.         } catch (Exception e) {
  26.             throw new RuntimeException(e);
  27.         } finally {
  28.             System.out.println("here is finally");
  29.             i++; // 2
  30.         }
  31.     }
  32. }
  33. ///////////////////////////////////////////////////
  34. public class Test {
  35.     public static void main(String[] args) {
  36.         System.out.println(example());
  37.     }
  38.     public static int example() {
  39.         int i = 0;
  40.         try {
  41.             i++; // 1
  42.             i = 1 / 0; // 算术异常
  43.             return i;
  44.         } catch (Exception e) {
  45.             i++; // 2
  46.             return i;
  47.         } finally {
  48.             System.out.println("here is finally");
  49.             i++; // 3
  50.         }
  51.     }
  52. }
  53. /////////////////////////////////////////////////////
  54. public class Test {
  55.     public static void main(String[] args) {
  56.         System.out.println(example());
  57.     }
  58.     public static int example() {
  59.         int i = 0;
  60.         try {
  61.             i++; // 1
  62.             i = 1 / 0; // 算术异常
  63.             return i;
  64.         } catch (Exception e) {
  65.             i++; // 2
  66.             return i;
  67.         } finally {
  68.             System.out.println("here is finally");
  69.             i++; // 3
  70.             return i;
  71.         }
  72.     }
  73. }
复制代码
3.try finally
try 可以直接跟 finally 搭配使用。
在这些演示中,似乎 finally 无论有没有出现异常都一定会执行,真的是这样吗?

  • 如果 try 或者 catch 退出程序,finally 不会执行
  • finally 语句块中出现异常,会抛出异常,且不再向下执行
  • 程序所在的线程死亡,finally 不会执行
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         System.out.println(example());
  4.     }
  5.     public static int example() {
  6.         int i = 0;
  7.         try {
  8.             i++; // 1
  9.             i = 1 / 0; // 算术异常
  10.             return i;
  11.         } catch (Exception e) {
  12.             System.exit(0); // 退出程序
  13.         } finally {
  14.             System.out.println("here is finally"); // finally不会执行
  15.         }
  16.         return 0;
  17.     }
  18. }
复制代码
3.异常抛出

1.自动抛出异常
当方法中出现异常,会自动创建一个对应的异常类对象。比如:数组越界就是 ArrayIndexOutOfBoundsException;空指针就是 NullPointerException。
2.手动抛出异常
开发人员可以在程序中通过 throw 关键字手动抛出异常。比如:在 catch 中手动抛出异常停止程序;个人学习、调试中手动抛出异常模拟程序异常。

  • throw 关键字:throw 表示一种动作,可以用于抛出异常,在方法体中使用。
  • throws 关键字:大家应该还见过 throws,放在方法头上,后面可以接多个异常类。throws 用来声明异常,若方法中存在编译时异常(非运行时异常),如果不对其捕获,则必须在方法头中显式声明该异常,以便于告知方法调用者此方法可能出现异常。
4.异常处理

java 异常处理遵循捕获、处理、传递的原则。当异常发生时,首先尝试在当前方法中找到匹配的 catch 块进行处理。如果没有找到,异常会向上传递到调用该方法的上级方法,直到找到匹配的 catch 块或者到达顶层被 jvm 处理。
如果一个异常在产生后没有被任何代码处理,它会被抛给 jvm。jvm 会终止当前线程,并打印出异常的堆栈跟踪信息。
在调用方法时,jvm 会将方法压入栈中,当方法执行完毕,会从栈顶弹出。当异常发生时:

  • jvm 尝试在当前方法内部找到可以处理异常的程序(catch 代码块)
  • 若当前方法中没有捕获异常,则该异常会被传递到这个方法的调用者
  • 循环过程:jvm 尝试在方法内部找到处理异常的程序,否则继续传递给方法调用者
  • 当异常被传递到最顶级(最底层)的方法,而这个方法也没有办法处理这个异常,则该异常会被 jvm 处理:

    • 打印异常信息
    • 停止程序(非正常停止)

5.自定义异常类

其实 java 已经内置了很多详细的异常类了。但是,在实际开发过程中,根据业务的要求,会出现一些跟业务相关的异常,需要程序员自己定义。
一个最基本的异常类应包含两个构造函数:无参构造函数和详细描述信息构造函数,这个异常类就已经可以使用了。
如果还有其他需求,可以在类中添加属性和方法实现。
  1. // 如果是运行时异常,就继承RuntimeException,如果是编译时异常就继承Exception
  2. public class UserNotFoundException extends RuntimeException{
  3.     // 空参构造
  4.     public UserNotFoundException() {
  5.         super();
  6.     }
  7.     // 带参构造,message就是异常的提示信息
  8.     public UserNotFoundException(String message) {
  9.         super(message);
  10.     }
  11. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

前天 22:07

举报

分享、互助 让互联网精神温暖你我
您需要登录后才可以回帖 登录 | 立即注册