java 异常体系详细介绍
一.异常概述与异常体系结构
异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)。
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable
作为所有异常的超类,有两个子类Error和Exception
,分别表示错误和异常。
Java程序在执行过程中所发生的异常事件可分为两类:
- Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError(堆栈溢出)和OOM(OutOfMemoryError内存用完)。一般不编写针对性的代码进行处理。
- Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:空指针异常、数组角标越界。
java中的Exception类的子类不仅仅只是像上图所示只包含IOException和RuntimeException这两大类,Exception的子类很多很多,主要可概括为运行时异常(RuntimeException)
和非运行时异常
,也称为不检查异常(Unchecked Exception)
和检查异常(Checked Exception)
。
- 运行时异常:都是RuntimeException类及其子类异常,如
NullPointerException、IndexOutOfBoundsException
等, 这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。 - 非运行时异常:是RuntimeException以外的异常,编译期间可以检查到的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。 如
IOException、SQLException
等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
二.try-catch-finally
Java提供的是异常处理的抓抛模型。
Java程序的执行过程中如出现异常,会生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。
1.异常对象的生成
由虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出——自动抛出
由开发人员手动创建:Exception exception = new ClassCastException();——创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样
2.异常抛出机制
若执行try块的过程中没有发生异常,则跳过catch子句。若是出现异常,try块中剩余语句不再执行。开始逐步检查catch块,判断catch块的异常类实例是否是捕获的异常类型。匹配后执行相应的catch块中的代码。
如果异常没有在当前的方法中被捕获,就会被传递给该方法的调用者。如果异常没有在调用者方法中处理,它继续被抛给这个调用方法的上层方法。这个过程一直重复,直到异常被捕获或被传给main方法(交给JVM来捕获),这一过程称为捕获(catch)异常。
如果一个异常回到main()方法,并且main()也不处理,则程序运行终止。
程序员通常只能处理Exception,而对Error无能为力。
3.异常处理机制
异常处理是通过try-catch-finally语句实现的。
try{
...... //可能产生异常的代码
}
catch( ExceptionName1 e ){
...... //当产生ExceptionName1型异常时的处置措施
}
catch( ExceptionName2 e ){
...... //当产生ExceptionName2型异常时的处置措施
}
[ finally{
...... //无论是否发生异常, 都无条件执行的语句
} ]
try
捕获异常的第一步是用try{…}语句块选定捕获异常的范围,将可能出现异常的代码放在try语句块中。
catch( Exception e)
在catch语句块中是对异常对象进行处理的代码。每个try语句块可以伴随一个或多个catch语句。对于try里面发生的异常,他会根据发生的异常和catch里面的进行匹配(按照catch块从上往下匹配),如果有匹配的catch,它就会忽略掉这个catch后面所有的catch。
在catch中可以捕获异常的有关信息:
- e.getMessage():获取异常信息,返回字符串
- e.printStackTrace():获取异常类名和异常信息及异常出现在程序中的位置。返回值void
finally
不论在try代码块中是否发生了异常事件,catch语句是否执行,catch语句是否有异常,catch语句中是否有return,finally块中的语句都会被执行;
finally中的return、throw会覆盖try、catch中的return、throw;
finally语句和catch语句是任选的。
public int test() {
try {
int a = 1;
a = a / 0;
return a;
} catch (Exception e) {
return -1;
} finally{
return -2;
}
} // 方法返回值:-2
当执行代码
a = a / 0;
时发生异常,try块中它之后的代码便不再执行,而是直接执行catch中代码;在catch块中,当在执行return -1
前,先会执行finally块;由于finally块中有return语句,因此catch中的return将会被覆盖,直接执行fianlly中的return -2
后程序结束。因此输出结果是-2。注意
- try、catch、finally三个语句块均不能单独使用,三者可以组成 try...catch...finally、try...catch、try...finally三种结构,catch语句可以有一个或多个,finally语句最多一个
- try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面
- 多个catch块时候,最多只会匹配其中一个异常类且只会执行该catch块代码,而不会再执行其它的catch块,且匹配catch语句的顺序为从上到下,也可能所有的catch都没执行
- 先Catch子类异常再Catch父类异常
三.throws
throws关键字用于方法体外部的方法声明部分,用来声明方法可能会抛出某些异常类型,也可以是它的父类。仅当抛出了检查异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出。
import java.io.*;
public class ThrowsTest {
public static void main(String[] args) {
ThrowsTest t = new ThrowsTest();
try {
t.readFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile() throws IOException {
FileInputStream in = new FileInputStream("data.txt");
int b;
while ((b=in.read()) != -1) {
System.out.print((char) b);
}
in.close();
}
}
重写方法不能抛出比被重写方法范围更大的异常类型 (<=)。在多态的情况下,对methodA()方法的调用-异常的捕获按父类声明的异常处理。
public class A {
public void methodA() throws IOException {
……
}
}
public class B1 extends A {
public void methodA() throws FileNotFoundException {
……
}
}
public class B2 extends A {
public void methodA() throws Exception { // 报错
……
}
}
四.throw
throw关键字是用于方法体内部,用来抛出一个Throwable类型或其子类的异常。
如果抛出了检查异常,则还应该在方法头部声明方法可能抛出的异常类型。该方法的调用者也必须检查处理抛出的异常。如果所有方法都层层上抛获取的异常,最终JVM会进行处理,处理也很简单,就是打印异常消息和堆栈信息。
public static void test() throws Exception
{
throw new Exception("方法test中的Exception");
}
throw和throws关键字的区别
- 写法上 : throw 在方法体内使用,throws 函数名后或者参数列表后方法体前
- 意义 : throw 强调动作,而throws 表示一种倾向、可能但不一定实际发生
- throws 后面跟的是异常类,可以一个,可以多个,多个用逗号隔开。throw 后跟的是异常对象,或者异常对象的引用。
- throws 用户抛出异常,在当前方法中抛出异常后,当前方法执行结束(throws 后,如果有finally语句的话,会执行到finally语句后再结束。)。可以理解成return一样
五.自定义异常类
一般地,用户自定义异常类都是RuntimeException的子类。
- 自定义异常类通常需要编写几个重载的构造器。
- 自定义异常需要提供serialVersionUID
- 自定义的异常通过throw抛出。
- 自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型。
语法:
// 1.定义异常类
class 自定义异常类 extends 异常类型(Exception) {
// 2.重载构造方法
// 3.将异常信息传递给父类:super(...)
}
示例:
// 备注: 这些方法怎么来的? 重写父类Exception的方法
public class CustomException extends Exception {
static final long serialVersionUID = 13465653435L;
//无参构造方法
public CustomException(){
super();
}
//有参的构造方法
public CustomException(String message){
super(message);
}
// 用指定的详细信息和原因构造一个新的异常
public CustomException(String message, Throwable cause){
super(message,cause);
}
//用指定原因构造一个新的异常
public CustomException(Throwable cause) {
super(cause);
}
}
总结: 异常处理的5个关键字
捕获异常:
- try:执行可能产生异常的代码
- catch:捕获异常
- finally:无论是否发生异常,代码总被执行
抛出异常:
- throw:异常的生成阶段:手动抛出异常对象
声明异常:
- throws:异常的处理方式:声明方法可能要抛出的各种异常类
java 异常体系详细介绍的更多相关文章
- Java 异常体系(美团面试)
Java把异常作为一种类,当做对象来处理.所有异常类的基类是Throwable类,两大子类分别是Error和Exception. 系统错误由Java虚拟机抛出,用Error类表示.Error类描述的是 ...
- java(异常体系及权限修饰符)
java异常体系 异常的体系: 异常体系: --------| Throwable 所有错误或者异常的父类 --------------| Error(错误) --------------| Exce ...
- Java异常体系概述
Java的异常体系结构 Java异常体系的根类是 Throwable, 所以当写在java代码中写throw抛出异常时,后面跟的对象必然是Throwable或其子类的对象. 其中Exception异常 ...
- JAVA异常体系
1.异常体系 ----|Throwable 所有错误或异常的父类 --------|Error(错误) --------|Exception(异常)一般能通过代码处理 ------------|运行时 ...
- Java异常体系简析
最近在阅读<Java编程思想>的时候看到了书中对异常的描述,结合自己阅读源码经历,谈谈自己对异常的理解.首先记住下面两句话: 除非你能解决这个异常,否则不要捕获它,如果打算记录错误消息,那 ...
- Java异常处理-----java异常体系
再三思考后还是决定贴图,csdn的格式,我是真玩不转,对不起了各位,继续将就吧. 错误原因:内存溢出.需要的内存已经超出了java虚拟机管理的内存范围. 错误原因:找不到类文件. 错误(Error): ...
- java之Stack详细介绍
1 Stack介绍 Stack简介 Stack是栈.它的特性是:先进后出(FILO, First In Last Out). java工具包中的Stack是继承于Vector(矢量队列)的,由于Ve ...
- Java基础系列5:深入理解Java异常体系
该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 前言: Java的基 ...
- Java——深入理解Java异常体系
该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 前言: Java的基 ...
随机推荐
- 18. ClustrixDB 管理CPU资源
作为一个分布式MPP数据库,ClustrixDB能够利用多个节点和核心来比单节点数据库更快地处理查询.有两个可调进程可以促进这一点. Clustrix选择了一组默认参数来控制那些提供最常见工作负载的进 ...
- Linux培训教程 linux中nl命令使用介绍
nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容自动的加上行号!其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补齐 0 等 ...
- 通过 PHP 生成 XML
如需使用 PHP 在服务器上生成 XML 响应,请使用下面的代码: <?php header("Content-type:text/xml"); echo "< ...
- es6的class关键字与es5的构造函数
1,构造函数 function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { ret ...
- UIImage非正方形图片如何剪切为正方形
有时候项目里做头像上传时候,必须要把用户从相册或是相机里的选择的图片剪切为指定大小的图片,遇到太大,太小或是太长的图片就需coregraphic来对图片进行剪切 废话不多说,直接上代码 /** * 剪 ...
- 为Sublime Text 3设置优雅的字体
本文使用的Sublime Text 3版本是3.2.1(build 3207),这个版本默认对中文的支持很糟糕,中国程序员很费眼睛,需要做一番设置. 首选需要在本机安装漂亮的字体,我们选用的是YaHe ...
- 浅谈javaweb三大框架和MVC设计模式
一.MVC设计模式 1.MVC的概念 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(Vie ...
- 分享页(把末尾的JS函数换成这个)
function jsApiStart(obj) { wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以 ...
- php语法标识符
php语法标识符 一.总结 一句话总结: 常用<?php //这里写代码 ?>:其它要么不常用,要么需要开配置 二.PHP四大标识符(语法环境) 参考或转自:PHP四大标识符(语法环境) ...
- [Python]ctypes+struct实现类c的结构化数据串行处理
1. 用C/C++实现的结构化数据处理 在涉及到比较底层的通信协议开发过程中, 往往需要开发语言能够有效的表达和处理所定义的通信协议的数据结构. 在这方面是C/C++语言是具有天然优势的: 通过str ...