异常
Throwable 类是 Java 语言中所有错误和异常的 Throwable 类
1、Error:JVM 无法解决的严重问题,程序崩溃
2、Exception:因编程错误或偶然的外在因素导致的一般性问题
(1)运行异常(RuntimeException):非必须处理,JVM 的正常操作期间可以抛出的那些异常的超类,RuntimeException 及其子类是未经检查的异常
(2)编译异常:必须处理
3、语法错误、逻辑错误不是异常
处理异常方式
1、try - catch - finally:捕获异常,自行处理
2、throws:抛出异常,交给调用者处理,JVM 为最顶级的处理者,JVM 处理异常:输出异常信息,退出程序
3、try - catch - finally、throws 二选一
(1)运行异常(RuntimeException):程序没有显式处理,默认 throws 处理,显式处理覆盖默认 throws 机制
(2)编译异常:程序必须显式调用 try - catch - finally 或 throws,无默认机制
try - catch - finally
try {
可能异常的代码
} catch (形参列表) {
对捕获异常的处理
} finally {
必须执行的代码
}
1、catch
(1)若发生异常,try 中发生异常之后的代码不会执行,直接进入 catch
(2)若不发生异常,执行完 try 中代码,不进入 catch,而进入 finally
(3)catch 的形参列表是声明捕获 try 中可能发生的异常
(4)可以有多个 catch 语句,要求子类异常类型在前,父类异常类型在后
2、finally 不是必须的
try {
可能异常的代码
} catch (形参列表) {
对捕获异常的处理
}
(1)通常用于释放资源
(2)不论是否发生异常,finally 代码都会执行
(3)若 try 和 catch 的代码块中有 return 时,finally 仍会在 return 前执行
(4)若 finally 中有 return,则会覆盖 try 和 catch 中的 return,即 finally 执行 return
(5)若 finally 没有 return,try 或 catch 中的 return 执行完成之前,return 表达式的结果会暂时保存起来
3、实际开发
try {
可能异常的代码
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
必须执行的代码
}
(1)捕获编译异常,在 catch 中将编译异常封装进运行异常,再使用 throw 抛出,实现编译异常转运行异常
(2)不论编译异常 / 运行异常,既可以捕获,又可以默认处理
try - finally
try {
可能异常的代码
} finally {
必须执行的代码
}
1、相当于没有捕获异常
2、执行完 try 中代码,不论是否发生异常,都执行 finally 中的业务逻辑
3、发生异常,执行完 finally 中的代码就退出程序;没有发生异常,继续执行 finally 后面的代码
4、假设利用 return 语句从 try 语句块中退出,在方法返回前,finally 子句的内容将被执行,如果 finally 子句中也有一个 return 语句,这个返回值将会覆盖原始的返回值
try - catch - finally 执行顺序
1、无异常
(1)try 无 return:try -> finally -> 继续往下执行
(2)try 有 return:try 执行 return 之前的代码-> finally -> 执行 try 中的 return
2、有异常
(1)catch 无 return:try 执行异常之前的代码-> catch -> finally -> 继续往下执行
(2)catch 有 return:try 执行异常之前的代码-> catch 执行 return 之前的代码 -> finally -> 执行 catch 中的 return
3、finally 是否存在 return
(1)finally 有 return,不论有没有异常、try 或 catch 中有没有 return:try 执行异常之前的代码 -> catch -> finally -> 执行 finally 中的 return
(2)finally 无 return,try、catch 有 return:运算 try / catch 中 return 后面的表达式 -> 保存 return 值 -> finally(不会改变 return 值)-> try / catch 中的 return
throws
访问修饰符 返回数据类型 方法名(形参列表) throws 异常类型1, 异常类型2 {
方法体;
}
1、不对异常处理,由方法调用者处理
2、throws 可以声明抛出异常列表,可以是方法中产生异常类型或是其父类异常类型
自定义异常
1、定义异常类,自定义异常类继承 Exception / RuntimeException
(1)Exception:属于编译异常(继承 Exception 而非 RuntimeException)
(2)RuntimeException:属于运行异常(继承 Exception)
2、一般继承 RuntimeException,因为有默认 throws 机制
3、throw、throws
意义 | 位置 | 后面编写 | |
throws | 处理异常的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |
异常的约束
1、子类方法
(1)子类方法的异常声明(throws)必须 <= 父类方法的异常声明(throws)
子类方法可以选择性地声明(throws)父类方法的异常声明,或部分声明,或全都不声明
子类方法声明(throws)的异常类型可以是父类方法所声明异常的子类
(2)子类实现接口的方法,异常声明(throws)同样受(1)约束
(3)父类和接口存在相同签名的方法,子类只能取该方法的异常声明(throws)的并集,因为接口不能扩展父类中方法的异常声明,同样父类也不能扩展接口中方法的异常声明
2、子类构造器
(1)异常约束对构造器不起作用
(2)子类构造器的异常声明(throws)必须 >= 父类构造器的异常声明(throws)
子类构造器必须包括父类构造器的异常声明(throws)
子类构造器能够声明(throws)父类构造器没有声明的异常
(4)子类构造器不能捕获(catch)父类构造器抛出的异常
3、异常与编译类型绑定
(1)编译器会强制只捕捉(catch)该类的异常声明(throws),但是如果将其向上转型为父类类型,编译器就会强制捕捉(catch)父类的异常声明(throws)
(2)尽管编译器会在继承过程中强制保证异常声明(throws)的执行,但是异常声明(throws)并不是方法类型的一部分,因此,不能依赖异常声明(throws)的不同来重载方法
(3)不能因为父类方法存在异常声明(throws),就认为它一定会存在于子类方法的异常声明(throws)中
try-with-resources
1、在 Java 7 之前,try 后面总是要跟着一个 {,但是现在它后面可以跟一个 ()
(1)括号中的内容叫作资源说明头(resource specification header)
(2)在 try-with-resources 定义子句中,即括号内创建的对象必须实现 java.lang.AutoCloseable 接口,该接口只有一个方法:close()
(3)Closeable 接口继承 AutoCloseable,因此过去支持 Closeable 的任何东西都可以配合 try-with-resources 使用
(4)资源说明头可以包含多个定义,用 ; 隔开(最后 ; 是可选的)
(5)在这个头部定义的每个对象都将在 try 块的末尾调用其 close(),而且会以与创建顺序相反的顺序关闭它们
(6)资源说明头实际上是被try 块包围的
2、try-with-resources 的 try 块可以独立存在,没有 catch 或 finally
3、新特性:try-with-resources 中的实际上的最终变量
(1)最初的 try-with-resources 要求将所有被管理的变量都定义在资源说明头,即 try 后面的括号列表之中
(2)JDK 9 增加了在 try 之前定义这些变量的能力,只要它们被显式地声明为最终变量,或者是实际上的最终变量即可
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战