【捕获异常】

硬件的错误、输入错误、物理限制等问题,都可能导致程序运行时的异常出现。

1.异常的分类层次

在java中,异常对象都是由Throwable类继承而来的,主要分为两大类:

Error和Exception类。

在Exception中又分为:

RuntimeException异常和非RuntimeException异常。

异常的分类有以下几种:

1.Error类层次的结构主要描述了java运行时系统的内部错误和资源耗尽等错误,如硬件错误、输入错误数据、系统崩溃等。出现这些系统内部的问题,除了通知用户并尽量安全退出,基本上程序员也无能为力了,所以这种情况一般不要求解决,当然,这种情况也很少出现。

2.RuntimeException的异常时指运行时异常,也称为未检查异常。一般是由于程序员自己的问题造成的,如错误的类型转换、数组访问越界、访问空指针等。这些都是可以通过程序员的细心处理和认真分析来避免的。如在转换类型时检查,通过检查下标来防止越界,使用变量前检查是否为空来杜绝空指针异常。

3.非RuntimeException异常,也就是已检查异常。常见的已检查异常主要有以下几种:java.io.IOEeception(IO异常,输入输出设备不存在,比如在文件的末尾读取数据)和java.io.FileNotFoundException(文件未找到异常)和java.lang.ClassNotFoundException(动态地装载某个类时,找不到此类)

注意:对于已检查异常必须处理,对于未检查异常可以处理也可以不处理

Java异常类层次结构图:

2.捕获和处理异常

语法规则:

  • 返回类型 方法名(参数)
  • {
  • try {
  • 可能出现的异常语句A
  • 可能出现的异常语句B
  • 可能出现的异常语句C
  • }
  • catch(异常类 e) {
  • //某种异常的引用
  • 异常处理的语句D
  • }
  • finally {
  • 最终一定会执行的语句E
  • }
  • 其他语句F
  • }

finally语句块内的语句无论在什么时候在什么情况下都会被执行,经常会写一些释放资源的语句。如果前面语句中有一个return的值,finally中也有一个return的值,那么返回的一定是fianlly中return的值。

finally和catch可以省略其中的一个,但是不能同时省略

示例:

  • public class ExceptionTest {
  • public static void main(String[] args) {
  • //写一个for循环和switch分支语句,一次运行会抛出异常的语句
  • for(int i = 0;i < 5;i++) {
  • int j = 0;
  • try {
  • System. out.println("本条语句正常" );
  • //每次运行1条语句,前4条抛出异常,最后一条不抛出异常
  • switch(i) {
  • case 0:   int zero = 0;
  • j = 1/zero; break;
  • case 1:   int b[] = null;
  • j = b[0]; break;
  • case 2: int c[] = new int [2];
  • j = c[3]; break;
  • case 3:   char ch = "hello".charAt(9); break;
  • case 4:   char cha = "abc".charAt(1); break;
  • }
  • System. out.println("前面的语句都没有异常抛出才会运行我" );
  • } catch(Exception e) {
  • System. out.println("第" + (i+1) + "次捕获异常");
  • System. out.println("显示的异常信息为:" + e);
  • } finally {
  • System. out.println("无论前面怎样,这条语句都会执行" );
  • }
  • }
  • }
  • }

上面代码中case的前四句话必定会抛出异常:

case:0是零做了除数;

case:1是数组没有赋值,也就是没有初始化就使用

case:2是数组越界

case: 3是字符串越界

结果:

3.异常的匹配

如果try语句后跟多个catch语句,那么排列的先后顺序如下所示:

1.如果多个catch语句块中所指定的异常类型级别相同或者没有任何派生关系,则catch语句排列无序。
2.如果多个catch语句块中所指定的异常类型相互之间有派生关系,则必须子类型的异常写在上面,父类型的异常写在下面。


【自定义和抛出异常】

1.自定义异常

当系统中已有的异常类型不能满足使用要求时,可以根据自己的需要抛出自定义异常的对象。
自定义异常类一般通过充当捕获异常的角色,所以从Exception类或者其他的捕获异常类继承就可以了
其语法格式如下:

  • class 类名 extends Exception {
  • 类体;
  • }

自定义的异常类一般都会编写必要的构造方法和一些适当的功能方法,而且一般都会有两个构造方法:

一个是无参的构造方法

一个是以字符串做参数的构造方法

以字符串做参数的构造方法可以在有出错信息的情况下创建异常对象。

示例:

  • //自定义异常类ReportNotFoundException,有两个构造方法
  • public class ReportNotFoundException extends Exception{
  • ReportNotFoundException() {
  • }
  • ReportNotFoundException(String mesg) {
  • super(mesg);//创建异常对象
  • }
  • }

2.抛出异常

在声明或者方法中抛出异常,主要内容和使用方法如下:
在编程中会遇到很多异常,如果该程序有能力解决,可以用try/catch方法主动获取和处理异常。当不具备对异常进行处理的能力时,则向上抛出异常,直到抛到能够处理异常的位置。

抛出异常的语法是:

  • 访问限制修饰符 [static] 方法名(参数列表) throws 异常序列 {
  • 方法体;
  • }

比如,有一个m方法抛出了IOException和InterruptedException。
代码如下:

  • public void m() throws IOException,InterruptedException {
  • 方法体;
  • }

throws用来声明该方法将有可能抛出的异常,将可能抛出的异常列在throws后面,用逗号隔开

在方法体中处理异常的时候,也可以将这两种捕获异常再抛出,使用throws语句就可以将一个异常对象抛出
语法格式为:

  • throw new 异常对象;

当一个方法中出现异常,而没有处理,则以异常对象为返回值返回调用处,然后逐级传递。如果一直没有捕获和处理,最终异常将返回虚拟机,虚拟机终止退出,程序结束。

示例:

自定义异常:

  • //自定义异常类ReportNotFoundException,有两个构造方法
  • public class ReportNotFoundException extends Exception{
  • ReportNotFoundException() {
  • }
  • ReportNotFoundException(String mesg) {
  • super(mesg);//创建异常对象
  • }
  • }

职员及相应方法:

  • public class Employee {//定义公开的职员类型
  • String name;
  • public Employee(String name) {
  • this.name = name;
  • }
  • public String getReport() throws ReportNotFoundException {
  • //定义职员找报表的方法,找不到报表就报自定义异常
  • if(Math.random() > 0.7) {//设定找到报表的几率是70%
  • throw new ReportNotFoundException(name + "找不到报表" );
  • }
  • return name + ",报表找到了" ;
  • }
  • }
  • class Manager {//定义经理类
  • Employee[] es;//职员数组
  • public Manager(Employee[] es) {
  • super();
  • this.es = es;
  • }
  • public String getReport() throws ReportNotFoundException {
  • //定义经理找报表的方法
  • StringBuffer sb = new StringBuffer();//StringBuffer定义经常变化的字符串
  • for(int i = 0;i < es.length;i++) {
  • sb.append( es[i].getReport());//经理让所有职员找报表
  • }
  • return sb.toString();
  • }
  • }
  • class CFO {//定义CFO类
  • Manager[] ms;
  • public CFO(Manager[] ms) {
  • super();
  • this.ms = ms;
  • }
  • public String getReport() {//CFO的找报表方法,CFO只找下面的经理要报表
  • try {
  • return ms [0].getReport();
  • } catch(ReportNotFoundException e) {
  • e.printStackTrace();//打印异常栈信息
  • }
  • return null ;
  • }
  • }
  • class CEO {//定义CEO类
  • CFO cfo;
  • public CEO(CFO cfo) {
  • super();
  • this.cfo = cfo;
  • }
  • public String getReport() {//CEO的找报表方法,调用CFO去找报表
  • return cfo.getReport();
  • }
  • }

测试:

  • //测试向上抛出方法和自定义异常
  • public class ExceptionTest2 {
  • public static void main(String[] args) {
  • Employee emone = new Employee("员工一");//创建员工对象
  • Employee emtwo = new Employee("员工二");
  • Employee emthree = new Employee("员工三");
  • Employee[] employees = new Employee[] {emone,emtwo,emthree};//创建员工数组
  • Manager[] managers = new Manager[] {new Manager(employees)};//创建经理数组
  • CFO cfo = new CFO(managers );//创建CFO对象
  • CEO ceo = new CEO(cfo);//创建CEO对象
  • System. out.println(ceo.getReport());//ceo对象调用找报表方法
  • }
  • }

结果:


小结:

  • try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
  • catch 块:用于处理try捕获到的异常。
  • finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。

在以下4种特殊情况下,finally块不会被执行:

1)在finally语句块中发生了异常。
2)在前面的代码中用了System.exit()退出程序。
3)程序所在的线程死亡。
4)关闭CPU。

  • try-catch-finally 规则(异常处理语句的语法规则):

1)  必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。
2) 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
3) catch 块与相应的异常类的类型相关。
4) 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
5) 可嵌套 try-catch-finally 结构。
6) 在 try-catch-finally 结构中,可重新抛出异常。

  • try、catch、finally语句块的执行顺序:

1)当try没有捕获到异常时:try语句块中的语句逐一被执行,程序将跳过catch语句块,执行finally语句块和其后的语句;

2)当try捕获到异常,catch语句块里没有处理此异常的情况:当try语句块里的某条语句出现异常时,而没有处理此异常的catch语句块时,此异常将会抛给JVM处理,finally语句块里的语句还是会被执行,但finally语句块后的语句不会被执行;

3)当try捕获到异常,catch语句块里有处理此异常的情况:在try语句块中是按照顺序来执行的,当执行到某一条语句出现异常时,程序将跳到catch语句块,并与catch语句块逐一匹配,找到与之对应的处理程序,其他的catch语句块将不会被执行,而try语句块中,出现异常之后的语句也不会被执行,catch语句块执行完后,执行finally语句块里的语句,最后执行finally语句块后的语句;

  • Throws抛出异常的规则:

1) 如果是不可查异常(unchecked exception),即Error、RuntimeException或它们的子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能顺利通过,但在运行时会被系统抛出。

2)必须声明方法可抛出的任何可查异常(checked exception)。即如果一个方法可能出现受可查异常,要么用try-catch语句捕获,要么用throws子句声明将它抛出,否则会导致编译错误

3)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。

4)调用方法必须遵循任何可查异常的处理和声明规则。若覆盖一个方法,则不能声明与覆盖方法不同的异常。声明的任何异常必须是被覆盖方法所声明异常的同类或子类。

  • 常见异常

在Java中提供了一些异常用来描述经常发生的错误,对于这些异常,有的需要程序员进行捕获处理或声明抛出,有的是由Java虚拟机自动进行捕获处理。Java中常见的异常类:

1.runtimeException子类:

1、 java.lang.ArrayIndexOutOfBoundsException

数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException

算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException

空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException

找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。

5、java.lang.NegativeArraySizeException

数组长度为负异常

6、java.lang.ArrayStoreException

数组中包含不兼容的值抛出的异常

7、java.lang.SecurityException

安全性异常

8、java.lang.IllegalArgumentException

非法参数异常

2.IOException

1、IOException:

操作输入流和输出流时可能出现的异常。

2、EOFException

文件已结束异常

3、FileNotFoundException

文件未找到异常

3. 其他

1、ClassCastException

类型转换异常类

2、ArrayStoreException

数组中包含不兼容的值抛出的异常

3、SQLException

操作数据库异常类

4、NoSuchFieldException

字段未找到异常

5、NoSuchMethodException

方法未找到抛出的异常

6、NumberFormatException

字符串转换为数字抛出的异常

7、StringIndexOutOfBoundsException

字符串索引超出范围抛出的异常

8、IllegalAccessException

不允许访问某类异常

9、InstantiationException

当应用程序试图使用Class类中的newInstance()方法创建一个类的实例,而指定的类对象无法被实例化时,抛出该异常

Java基础——异常机制的更多相关文章

  1. Java的异常机制

    Java的异常机制 (一)异常的概念 异常是指程序在编译或运行时出现的导致程序不能继续编译或运行的状况.. (二)Throwable类 Throwable类继承自Object类,是Java中所有错误或 ...

  2. Java基础-类加载机制与自定义类Java类加载器(ClassLoader)

    Java基础-类加载机制与自定义类Java类加载器(ClassLoader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于类加载器的概念和分类我就不再废话了,因为我在之前的笔 ...

  3. Java基础-异常(Exception)处理

    Java基础-异常(Exception)处理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.异常的概述 什么是异常?Java代码在运行时期发生的问题就是异常.在Java中,把异 ...

  4. 关于java中异常机制

    什么是异常:异常就是程序在运行时出现的不正常情况.对于严重的情况Java通过Error类进行描述,一般不用编写代码处理:对于不严重的情况Java通过Exception描述,一般编写针对性代码对其进行处 ...

  5. 《Java基础——异常的捕获与抛出》

    Java基础--异常的捕获与抛出     '  前言: Error类(错误)和Exception类(异常)是Throwable类的子类. 异常分为CheckedException类(编译时异常)和Ru ...

  6. Java基础 - 异常详解

    异常的层次结构 Throwable Throwable 是 Java 语言中所有错误与异常的超类. Throwable 包含两个子类:Error(错误)和 Exception(异常),它们通常用于指示 ...

  7. Java基础——异常体系

    在Java中,异常对象都是派生于Throwable类的一个实例,Java的异常体系如下图所示: 所有的异常都是由Throwable继承而来,在下一层立即分解为两个分支,Error和Exception. ...

  8. JAVA基础——异常详解

    JAVA异常与异常处理详解 一.异常简介 什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错.在java中,阻止当前方法或作用域的情况,称之为异常. java中异常的体系是怎么样的呢? 1 ...

  9. Java基础-异常、断言

    处理错误 如果Java程序运行期间出现了错误,并且由于出现错误导致某些操作没有完成,程序应该能够返回到一种安全状态,并能够让用户执行一些其他的命令:或者允许用户保存所有操作结果,并以妥善的方式终止程序 ...

随机推荐

  1. TCP/IP 编程

    http://www.cnblogs.com/ggjucheng/archive/2012/08/18/2645324.html

  2. PCAP 抓包

    PCAP是一个数据包抓取库, 很多软件都是用它来作为数据包抓取工具的. WireShark也是用PCAP库来抓取数据包的.PCAP抓取出来的数据包并不是原始的网络字节流,而是对其进行从新组装,形成一种 ...

  3. java反射性能

    项目中用到了java的反射,可以大大减少代码量.但是反射的性能却不容乐观,做了个简单的测试,如下. public void noreflect() { Person p = new Person(); ...

  4. Ⅱ.AngularJS的点点滴滴--缓存

    模板缓存-$templateCache and 缓存工厂 $cacheFactory 1.使用script标签 <html ng-app> <script src="htt ...

  5. git操作github

    转自http://www.cnblogs.com/fnng/archive/2012/01/07/2315685.html 怕找不到~ 本文在我之前的那篇<git/github学习笔记>的 ...

  6. iOS UIKit:TabBar Controller

    1 结构剖析 IOS中的标签导航其实是一个UITabBarController对象,其也是一个Container View Controller.UITabBarController对象创建和管理了一 ...

  7. PHP中用PDO方法打开连接关闭mysql数据库

    代码如下: <meta http-equiv="content-type" content="text/html" charset="utf-8 ...

  8. day-9

    /* 考前第9天 区间*的线段树居然卡住了23333 明天再搞搞 今天针对考试复习了几个板子 手动堆都打了 实测比priority快 下午考试成了炮灰233333 晚上复习矩阵乘法 手推9*9矩阵 可 ...

  9. 用Eclipse+xdebug调试PHP总是在首行自动断点解决方法

    问题描述: 使用Eclipse+PDT+xdebug调试PHP程序时,总是在程序的第一行(首行)自动断点,不方便调试. 解决方法: 分别在下面3个位置配置,取消 Break at First Line ...

  10. 使用html5兼容低版本浏览器

    因为html5 新出的一些语义化的标签,在低版本浏览器下不能识别,举个例子,比如你写了一个 header 标签中,写了一段文本,在低版本浏览器下,肯定是能看到的,但是,那是他是不认识 header标签 ...