异常

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 之前定义这些变量的能力,只要它们被显式地声明为最终变量,或者是实际上的最终变量即可

posted @   半条咸鱼  阅读(36)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示