Chapter 9 异常

异常:指程序在执行过程中,出现的非正常的情况,最终导致JVM非正常停止。

在Java等面向对象的编程语言中,异常是一个,所有异常都是发生在运行阶段的(因为也只有程序运行阶段方可new 对象),产生异常其实就是创建异常对象。而Java处理异常的方式为中断处理。

9.1 异常体系

如下的UML图关于异常的继承结构,异常的根类为java.lang.Throwable(顾名思义,所有异常均可抛出),其下有两个子类:java.lang.Errorjava.lang.Exception。而我们平常所说的异常指的是后者。

  • 错误(Error):Java程序运行过程中若发生错误,则无法恢复,只能够退出。
  • 编译时异常(CheckException,或称受控异常、检查异常):出现了这种类型的异常必须显式地处理,若不处理则Java程序将无法编译通过。
  • 运行时异常(RuntimeException,或称UncheckedException,未检查异常,非受控异常):此种异常发生几率低,可以不用显式地处理(eg: 算术异常),也能够编译通过。

异常信息的获取:

Throwable类中定义了一些查看方法:

  • public String getMessage():获取异常的描述信息与原因,多用于向用户提示错误的原因。

  • public void printStackTrace():打印异常的跟踪栈信息并输出至控制台。(开发与调试阶段常用)

9.2 异常处理机制

Java异常的作用是增强程序健壮性。

9.2.1 声明异常throws

Java的一个方法不仅需要告诉编译器将要返回什么值,还需要告诉编译器有可能发生什么错误。

一个方法必须声明所有可能抛出的已检查异常(CheckedException),而未检查异常要么是不可控制的Error,要么是应该避免发生的未检查异常(RuntimeException)

故,方法应在其首部throws声明可能发生的异常(但不一定会发生),其格式为:

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

  • 例如:public FileInputStream(String name) throws FileNotFoundException

    这个声明表示该构造器由String参数产生一个FileInputStream对象,但也有可能抛出一个FileNotFoundException类对象。若该方法真的抛出了这样一个异常对象,运行时系统就会开始搜索异常处理器,以便知道如何处理FileNotFoundException对象。

在Java中,没有throws说明符的方法将不能抛出任何已检查异常,它是可以单独使用的。一旦对该方法进行throws声明,必须交由调用该方法的上一级方法的语句来处理(捕获 或 继续声明),若调用者不进行处理,编译一般不能通过!

运行时异常被抛出可以不处理,即允许不捕获也不声明抛出。

注意:Java中异常发生后若一直往上抛,最终抛给main方法,main方法继续向上抛,抛给调用者JVM,JVM知道这个异常发生后会终止Java程序运行。

9.2.2 抛出异常throw

在Java中,提供throw关键字,用在方法内,抛出一个异常对象,将该异常对象传递到调用者处,并直接结束当前方法的执行。

格式为throw new 异常类名(参数); 或者 异常类 异常对象名 = new 异常类名(参数); throw 异常对象名

String readData(Scanner in) throws EOFException{ //声明可能出现的异常
//...
while(...){
if(!in.hasNext()){
...
if(n < len) throw new EOFException(); //创建异常对象,并将其抛出
}
}
return s;
}

抛出异常的4种情况:

  1. 调用一个抛出已检查异常的方法,例如,FileInputStream 构造器。
  2. 程序运行过程中发现错误,并且利用 throw 语句抛出一个已检查异常。
  3. 程序出现错误。例如,a[-1] = 0;
  4. Java虚拟机和运行时库出现的内部异常。

一般而言,throw语句不能单独使用,它应与throws声明配套使用。

我们一般是使用一次捕获 多次处理方式,格式如下:

try{
//编写可能会出现异常的代码
} catch(异常类型A e){
//处理A类型异常
} catch(异常类型B e){
//处理B类型异常
}

注意,这种异常处理方式,要求多个catch中异常不能相同,且catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

9.2.3 捕获异常try-catch

捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行制定方式的处理。要想捕获一个异常,必须设置try...catch语句块。语法格式如下:

try{
//编写可能产生异常的代码。(一般调用方法,该方法声明了异常并能够对异常抛出)
} catch(异常类型 异常名){
//处理异常的代码:记录日志/打印异常信息/继续抛出异常
}

如果在try语句块中任何代码抛出一个在catch子句中说明的异常类,那么:

  1. 程序将跳过try语句块的其余代码;
  2. 程序将执行catch子句中的处理器代码。

举例如下:

public class JustTest {
public static void main(String[] args) {
try{
read(b.txt);
} catch(FileNotFoundException e){
System.out.println(e); //try中抛出的是什么异常,在括号中就定义什么异常类型
}
System.out.println("Over!");;
}
public static void read(String path) throws FileNotFoundException{
if(!path.equals("a.txt")){
throw new FileNotFoundException("文件不存在");
}
}
}

9.2.4 finally 代码块

当代码抛出一个异常时,就会终止方法中剩余代码的处理,并退出这个方法的执行。当我们在try语句块中打开一些物理资源(磁盘文件/网络连接/数据库连接等),我们需要在使用完之后关闭已打开的资源。注意,finally不能单独使用。

public class JustTest {
public static void main(String[] args) {
try{
read(b.txt);
} catch(FileNotFoundException e){
System.out.println(e); //try中抛出的是什么异常,在括号中就定义什么异常类型
} finally {
System.out.println("不管程序如何,我会被执行的~");
}
System.out.println("Over!");;
}
public static void read(String path) throws FileNotFoundException{
if(!path.equals("a.txt")){
throw new FileNotFoundException("文件不存在");
}
}
}

finally子句中的代码是一定会执行的!如果try语块有返回值,finally子句也会执行完再最后返回(除非使用System.exit(0);则会中断finally子句的执行)

public class JustTest {
public static void main(String[] args) {
int f = Judge();
System.out.println(f);
}
public static int Judge() {
try{
System.out.println("11111");
return 0;
} finally {
System.out.println("233333");
}
}
}

finally语句块设计的目的仅是为了让方法执行一些重要的收尾工作,而不是用来计算返回值的,故在finally语句块中修改返回值是无效的!同时不建议在finally语句块中返回一些值。

关于finalfinallyfinalize的区别

  • final 属于关键字,其修饰的类无法继承、修饰的方法无法覆盖、修饰的变量不能重新赋值。
  • finally 属于关键字,与try...catch联合使用,finally语句块中的代码是必须执行的。
  • finalize 标识符,是一个Object类中的方法名,该方法是由垃圾回收器GC负责调用。

9.3 自定义异常

在实际开发中总是有些异常情况是SUN没有定义的,根据自己业务的异常情况来定义异常类。

自定义异常类的方式:

  • 自定义一个编译时异常类:自定义类,并继承于java.lang.Exception
  • 自定义一个运行时期的异常类:自定义类,并继承于java.lang.RuntimeException

习惯上,定义的类应包含两个构造器,一个是默认无参构造器,另一个是带有详细描述信息的构造器。

public class RegisterException extends Exception{
public RegisterException(){ //无参构造
}
public RegisterException(String message){
super(message); //超类Throwable的toString方法将会打印出这些详细信息,调试中有用。
}
}

JavaSE 学习笔记04丨异常的更多相关文章

  1. JavaSE 学习笔记01丨开发前言与环境搭建、基础语法

    本蒟蒻学习过C/C++的语法,故在学习Java的过程中,会关注于C++与Java的区别.开发前言部分,看了苏星河教程中的操作步骤.而后,主要阅读了<Java核心技术 卷1 基础知识>(第8 ...

  2. JavaSE 学习笔记02丨对象与类

    Chapter 4. 对象与类 4.1 面向对象程序设计概述 面向对象程序设计(简称OOP),是当今主流程序设计范型.面向对象的程序是由对象组成的,每个对象(来自于标准库或自定义的)包含对用户公开的特 ...

  3. JavaSE学习笔记04方法、数组

    1.方法 java方法是语句的集合,它们在一起执行一个功能 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 设计方法的原则:一个方法只完成1个功能,这样 ...

  4. JavaSE 学习笔记07丨IO流

    Chapter 13. IO流 13.1 File类 java.io.File类是文件(file)和目录(文件夹)(directory)路径名(path)的抽象表示,主要用于文件和目录的创建.查找和删 ...

  5. JavaSE 学习笔记05丨泛型、集合

    Chapter. 10 泛型 10.1 泛型程序设计 泛型,指可以在类或方法中预支地使用未知的类型.泛型程序设计(Generic programming),意味着编写的代码可被很多不同类型的对象所重用 ...

  6. JavaSE 学习笔记03丨继承、接口、多态、内部类

    Chapter. 5 继承 继承作为面向对象的三大特征之一,它是多态的前提.它主要解决的问题是共性抽取. Java中的继承,是单继承.多级继承的. 已存在的类,被称为超类.基类.父类(parent c ...

  7. Linux 学习笔记04丨Linux的用户和用户组管理

    Chapter 3. 用户和用户组管理 由于Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以该账号身份进入系统. 3.0 用户与 ...

  8. JavaSE 学习笔记08丨网络编程

    Chapter 14. 网络编程 14.1 计算机网络入门 当前节的知识点只是一个概述,更具体.详细的内容放在 计算机网络 中. 14.1.1 软件结构 C/S结构(Client/Server结构): ...

  9. JavaSE 学习笔记06丨并发

    Chapter 12. 并发 12.1 并发与并行 并发:指两个或多个事件在同一个时间段内发生. 并行:指两个或多个事件在同一时刻发生(同时发生). 在操作系统中,并发指的是在一段时间内宏观上有多个程 ...

随机推荐

  1. 一、ETL实践之数据可视化架构

    开篇心声: 不管是学习新知识,还是遇到各种难题,总能在技术论坛找到经验帖子.一直享受大家提供的帮助,而自己没有任何输出,实在过意不去.我相信技术是经验的交流,思维的碰撞. 这是我一次写技术分享文章,我 ...

  2. D. Rescue Nibel! 解析(思維、組合、離散化、差分)

    Codeforce 1420 D. Rescue Nibel! 解析(思維.組合.離散化.差分) 今天我們來看看CF1420D 題目連結 題目 給你\(n\)個區間,求有幾種方法使得\(k\)個區間的 ...

  3. day78:luffy:前端对于token的认证&滑动验证码的实现

    目录 1.前端对于token的认证 2.滑动验证码 1.滑动验证码实现的原理 2.滑动验证码的代码实现 1.配置文件 2.前端实现:Login.vue 3.后端实现:改写jwt代码 1.前端对于tok ...

  4. SP22343 Norma--序列分治

    Norma 传送门 题意简化: 定义一个区间的贡献为 \(max*min*len\),求给定序列中所有子区间的总贡献和 题解 考虑 \(O(n*log_2n)\) 的复杂度的做法 数据结构??? yz ...

  5. 嵌入式linux和stm32嵌入式开发这两者之间有什么关联性

    对于更开始入坑的同学,可能也像我一样搞不清楚两者的区别与联系.现在结合知乎网上的相关资料发一篇文章来具体分析. 基于STM32的开发属于微控制器开发领域,主要开发工具是keil或IAR,这种开发更准确 ...

  6. wepack配置

    一.什么是 webpack? webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX).coffee.样式(含less/sass).图片等都作为模块来使用和处理,它能有Grunt ...

  7. monkey及其的日志管理和分析

    1.   monkey 1.1.  介绍 通过monkey程序模拟用户触摸屏幕,滑动Trackball.按键等操作来对设备上的程序进行压力测试,检测程序多久的时间会发生异常,检查和评估被测程序的稳定性 ...

  8. SQL service 数据插入

    目的:实现对数据库XDSA中表S72.C72.SC72的数据插入 1.构建数据库 2.构建表 3.插入数据 插入数据语句: ① 命令: INSERT INTO TableNameVALUES('值', ...

  9. leetcode 98:n-queens-ii

    题目描述 继续思考"n-queens"问题 这次我们不是输出皇后的排列情况,而是输出n皇后问题一共有多少种解法 Follow up for N-Queens problem. No ...

  10. HTML生成横向的PDF

    HTML生成PDF请参照:https://www.cnblogs.com/yunfeiyang-88/p/10984740.html 如要生成横向的PDF:在html模板的style标签里面加入@pa ...