JavaSE笔记-异常处理机制
异常概述
(1)在Java语言中,将程序运行过程中,由于某些原因导致程序出错,从而结束程序运行,称为“异常” (开发过程中的语法错误和逻辑错误不是异常)
(2)在 Java 中一个异常的产生,主要有如下三种原因
| 异常事件 | 简介 |
|---|---|
| Error(错误) | Java 内部错误发生异常,Java 虚拟机产生的异常,Java虚拟机无法解决的严重问题,一般不编写针对性的代码进行处理例如:JVM系统内部错误、资源耗尽等严重情况 |
| Exception(异常) | 因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理例如:空指针访问、数组角标越界、试图读取不存在的文件、网络连接中断等 这种异常称为未检査的异常,一般需要在某些类中集中处理这些异常 |
| throw生成 | 通过 throw 语句手动生成的异常 这种异常称为检査的异常,一般用来告知该方法的调用者一些必要的信息 |
(3)异常主要分为两种,分别是编译时异常和运行时异常(只要一个异常类的祖先类中有RuntimeException,那么就是运行时异常,否则是编译时异常)
| 异常分类 | 简介 |
|---|---|
| 编译时异常 | 是指编译器要求必须处置的异常,即程序在运行时由于外界因素造成的一 般性异常。 编译器要求Java程序必须捕获或声明所有编译时异常,对于这类异常,如果程序不处理,可能会带来意想不到的结果 |
| 运行时异常 | 是指编译器不要求强制处置的异常,一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。 java.lang.RuntimeException类及它的子类都是运行时异常。 对于这类异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。 |
异常体系结构

严重错误(Error)
堆溢出(OutOfMemoryError)
1 | // java.lang.OutOfMemoryError堆溢出代码示例 |
栈溢出(StackOverflowError)
1 | // java.lang.StackOverflowError栈溢出代码示例 |
编译时异常和运行时异常(Exception)
编译时异常
1 |
|
运行时异常(RuntimeException)
算数的异常(ArithmeticException)
1 |
|
输入类型与获取类型不匹配(InputMismatchException)
1 |
|
格式异常(NumberFormatException)
1 |
|
类型转换异常(InputMismatchException)
1 |
|
角标越界(IndexOutOfBoundsException)
1 |
|
空指针异常(NullpointerException)
1 |
|
异常的处理
程序员通常只能处理Exception,而对Error无能为力,子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
| 异常处理 | 简介 |
|---|---|
| 抛出异常(throw) | 只是将异常抛给了方法的调用者,并没有真正将异常处理掉,在方法声明的位置上使用throws关键字向上抛出异常,异常抛给了当前方法的调用者,即谁调用这个方法,谁就会得到这个异常,可以使用throws关键字将异常抛出,由于是JVM调用的main方法,所以这个异常抛给了JVM,JVM会将异常信息打印到控制台 |
| 捕获异常(try-catch) | 真正的将异常给处理掉了,如果一个方法内抛出异常,该异常对象会被抛给调用者方法中处理。 如果异常没有在调用者方法中处理,会继续被抛给这个调用方法的上层方法,此过程将一直继续下去,直到异常被处理 |
捕获异常(catch)
try-catch-finally捕获异常
try块中包含可能抛出异常的代码。如果发生异常,会根据异常类型进入相应的catch块进行处理。无论是否发生异常,finally块中的代码都会执行。
(1)使用try将可能出现异常代码包装起来
(2)一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型、去catch中进行匹配
(3)一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理
(4)一旦处理完成,如果没有写finally,就跳出当前的try-catch结构,继续执行其后的代码
(5)如果写了finally,那么finally中声明的代码一定会被执行,即使catch中又出现异常了或者try中有return语句,catch中有return语句等情况
1 | try { |
try-catch-finally注意事项
(1)catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。如果满足子父类关系,则要求子类一定声明在父类的上面,否则会报错
(2)try-catch-finally结构可以嵌套,在try结构中声明的变量,在出了try结构以后,就不能再被调用
(3)像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,需要自己手动的进行资源的释放(如close关闭操作),此时的资源释放,就需要声明在finally中
(4)使用try-catch-finally处理编译时异常,使得程序在编译时就不再报错,但是运行时仍可能报错,相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现
(5)开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了,针对编程时的异常,我们一定要考虑异常的处理
常见的异常处理方式
| 方法 | 简介 |
|---|---|
| e.toString() | 获得异常种类和错误信息 |
| e.getMessage() | 获得错误信息 |
| e.prntStackTrace() | 在控制台打印出异常种类,错误信息和出错位置等 |
try-catch-finally代码示例
示例一
1 |
|
示例二
1 |
|
try-with-resources捕获异常
try-with-resources语法
在Java7以前,程序中使用的资源需要被明确地关闭,在Java7之后,提供了一个新的异常处理机制try-with-resources,除了拥有try-catch-finally的所有功能,还提供了自动关闭资源的能力,能够在代码执行完毕后自动关闭 try 块中声明的资源,而无需显式地调用资源对象的 close() 方法,语法如下
1 | try ( |
try-with-resources注意事项
(1)在 try() 块中,我们需要先声明并初始化所有需要使用的资源,多个资源之间使用分号隔开。
(2)每一个资源都必须实现 AutoCloseable 接口或其子接口 Closeable 才能够被用于 try-with-resources 语句中。
(3)在 try() 块结束时,Java 会自动帮助我们关闭所有已经打开的资源,不需要手动进行资源释放。
(4)如果在 try-with-resources 接口中同时声明多个资源,则资源是按照声明顺序逆序关闭的,即先声明的资源会先被关闭
(5)catch 和 finally 语句块与传统的 try-catch-finally 结构一样,用于处理异常和一些清理工作。
抛出异常(throw)
| 对比 | 区别 |
|---|---|
| throw | 用在方法体内,后面跟的是异常对象,只能抛出一个异常对象,表示抛出异常,由方法体内的语句处理或抛出 |
| throws | 用在方法声明中,后面跟的是异常类,后面可以跟多个异常类名,用逗号隔开,表示抛出异常,由该方法的调用者来处理 |
使用throw语句抛出异常对象
(1)throw语法:异常对象可以是任何继承自Throwable类的子类的实例
1 | throw new 异常对象; |
(2)使用throw关键字手动抛出一个异常类对象
1 | public class ReturnException { |
使用throws关键字抛出异常
(1)throws的作用是抛出异常,在方法声明的位置上使用throws关键字向上抛出异常,异常抛给了当前方法的调用者,即谁调用这个方法,谁就会得到这个异常
(2)语法如下
1 | // 使用throws关键字将异常类型列表抛出,表示该方法可能抛出这些异常类型之一 |
(3)由于是JVM调用的main方法,所以这个异常抛给了JVM,JVM会将异常信息打印到控制台
自定义异常类
(1)一般用户自定义异常类都是RuntimeException的子类,使用时需要通过throw抛出
(2)自定义异常类的步骤
1 | 1、继承于现有的异常结构:RuntimeException 、Exception |
(3)自定义异常MyException代码示例
1 | public class MyException extends Exception { |











