Java 异常处理机制(全)

1 异常概述与异常体系结构

1.1 异常定义

    (1)在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式,读取文件是否存在,网络是否始终保持通畅等等。

    (2)在 Java 语言中,将程序执行中发生的不正常情况称为“异常” 。 ( 开发过程中的语法错误和逻辑错误不是异常 )

1.2 异常事件分类

Error

Java 虚拟机无法解决的严重问题,一般不编写针对性的代码进行处理。

Error 类描述内部错误,由系统保留,程序不能抛出这个类型的对象,Error 类的对象不可捕捉,不可恢复,出错时由系统通知用户并终止程序。

如:JVM 系统内部错误、资源耗尽等严重情况。比如:StackOverflowError 和 OOM。

Exception

其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。

Exception 类供应用程序使用,所有的 Java 异常类都是系统类库中 Exception 类的子类。

如:空指针访问、试图读取不存在的文件、网络连接中断、数组角标越界

 1.异常解决方法

     (1)遇到错误就终止程序的运行。

    (2)由程序员在编写程序时,就考虑到错误的检测、错误消息的提示、以及错误的处理。

1.4 Exception 分类

运行时异常

(非受检异常)

指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。

java.lang.RuntimeException 类及它的子类都是运行时异常。

对于运行时异常,可以不作处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。

编译时异常

(受检异常)

指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求 Java 程序必须捕获或声明所有编译时异常。

对于这类异常,如果程序不处理,可能会带来意想不到的结果。

1.5 异常继承结构

1.6 常见异常

    (1)java.lang.RuntimeException:运行时异常

ClassCastException:

类型转换异常

ArrayIndexOutOfBoundsException:

数组下标越界异常

NullPointerException:

空指针异常

ArithmeticException:

算术异常

NumberFormatException:

数字格式异常

InputMismatchException:

输入不匹配异常

    (2) java.io.IOExeption: IO 异常

FileNotFoundException:

文件未找到异常

EOFException:

end of file ,文件到达结尾异常

    (3) java.lang.ClassNotFoundException:类未找到异常

    (4) java.lang.InterruptedException:中断异常

    (5) java.sql.SQLException:SQL 异常

2. 异常处理机制一:try-catch-finally

2.1 问题引入

    (1)在编写程序时,经常要在可能出现错误的地方加上检测的代码,如进行 x/y 运算时,要检测分母是否为 0,数据为空,输入的不是数据而是字符等。过多的 if-else 分支会导致程序的代码加长、臃肿,可读性差。因此 Java 提供了异常处理机制。

────────────────────────────────────────────────────────────

2.2 Java 异常处理机制

    (1)可以方便在程序中监视可能发生异常的代码块,并将所有异常处理代码集中放置在程序某处,使完成正常功能的程序代码与进行异常处理的程序代码分开。使得降低编程人员的工作量,增强了异常处理的灵活性,使得程序的可读性和可维护性大为提高,简洁、优雅、并易于维护

    (2)在 Java 的异常处理机制中,引入一些用来描述和处理异常的类,每个异常类反映一类运行错误,在类的定义中包含了该类异常的信息和对异常进行处理的方法。当程序运行的过程中发生某个异常现象时,系统就产生一个与之相应的异常类对象,并交与系统中的相应机制进行处理,以避免系统崩溃或其他对系统有害的结果发生,保证了程序运行的安全性

────────────────────────────────────────────────────────────

2.3 异常对象的生成方式

    (1)虚拟机自动生成:程序运行过程中,虚拟机检测到程序发生了问题,如果在当前代码中没有找到相应的处理程序,就会在后台自动创建一个对应异常类的实例对象并抛出(自动抛出)

    (2)开发人员手动创建:Exception exception = new ClassCastException(); 创建好的异常对象不抛出对程序没有任何影响,和创建一个普通对象一样。

────────────────────────────────────────────────────────────

2.4 异常处理:抓抛模型

Java 程序的执行过程中如果出现异常,会生成一个异常类对象,该异常对象将被提交给 Java 运行时系统,这个过程称为抛出( throw )异常

捕捉异常—>程序流程的跳转—>异常处理语句块的定义异常的处理方式

────────────────────────────────────────────────────────────

2.5 捕捉异常

    (1)如果一个方法内抛出异常,该异常对象会被抛给调用者方法中处理。如果异常没有在调用者方法中处理,它继续被抛给这个调用方法的上层方法。这个过程将一直继续下去,直到异常被处理。这一过程称为捕获(catch)异常。如果一个异常回到 main() 方法,并且 main() 也不处理,则程序运行终止。

    (2)程序员通常只能处理 Exception,而对 Error 无能为力。

    (3)捕获异常的有关信息方法:

异常对象.getMessage()

获取异常信息,返回字符串

异常对象.printStackTrace()

获取异常类名和异常信息,以及异常出现在程序中的位置。返回值 void。

────────────────────────────────────────────────────────────

2.6 try—catch—finally 的语法格式使用

try{

//选定捕获异常的范围,将可能出现异常的代码放在 try 语句块中    

}

catch(异常类型1 变量名1){     

//处理异常的方式1        

}

catch(异常类型2 变量名2){     

//处理异常的方式2        

}

 ...

finally{     

//一定会执行的代码     

}

────────────────────────────────────────────────────────────

2.7 try—catch—finally 的使用

try

捕获异常的第一步是用 try{…} 语句块选定捕获异常的范围,将可能出现异常的代码放在 try 语句块中。

catch(可选)

在 catch 语句块中是对异常对象进行处理的代码。每个 try 语句块可以伴随一个或多个 catch 语句,用于处理可能产生的不同类型的异常对象。如果被捕捉的各类异常之间没有父子关系,各类的顺序无关紧要,如果有父子关系,应该将子类的 catch 块放置在父类的 catch 块之前。

finally(可选)

捕获异常的最后一步是通过 finally 语句为异常处理提供一个统一的出口,使得在控制流转到程序的其它部分以前,能够对程序的状态作统一的管理。不论在 try 代码块中是否发生了异常事件,catch 语句是否执行,catch 语句是否有异常,catch 语句中是否有 return,finally 块中的语句都会被执行。

try—catch—finally 可以使代码可以在编译时通过,但运行时仍可能会出错

在 try 中声明的变量,在 try 结构外无法再使用,可以在外部声明赋值,try 内部使用

一旦出现异常,try 内异常代码后的代码将不会执行,直接执行到相应的 catch 异常处理中

3. 异常处理机制二:throws

3.1 throws + 异常类型

    (1)throws + 异常类型写在方法的声明处,指明方法执行时可能抛出的异常类型,一旦方法执行时出现异常,就会在异常代码处生成一个异常类的对象,此对象满足 throws 后面的类型时,就会被抛出,异常后的代码不会再执行。

────────────────────────────────────────────────────────────

3.2 throws 和 try—catch—finally 的区别

try - catch - finally:

真正的异常处理

throws:

将异常抛给了方法的调用者

────────────────────────────────────────────────────────────

3.3 开发中如何选择使用 try-catch-finally 还是使用 throws?

    (1)如果父类中被重写的方法没有 throws 方式处理异常,则子类重写的方法也不能使用 throws,意味着如果子类重写的方法中有异常,必须使用 try-catch-finally 方式处理。

    (2)执行的方法 a 中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用 throws 的方式进行处理。而执行的方法 a 可以考虑使用 try-catch-finally 方式进行处理。

────────────────────────────────────────────────────────────

3.4 重写方法声明抛出异常的原则

    (1)重写方法不能抛出比被重写方法范围更大的异常类型。在多态的情况下, 对 methodA() 方法的调用-异常的捕获按父类声明的异常处理。

4 手动抛出异常:throw

4.1 异常对象的产生

    (1)Java 异常类对象除在程序执行过程中出现异常时由系统自动生成并抛出,也可根据需要人工创建异常对象并抛出(throw)。

    (2)格式:throw 异常类型

    (3)使用场景:需要自定义规则的时候抛出不符合规则的异常

    (4)要求:可以抛出的异常必须是 Throwable 或其子类的实例。

首先手动创建异常类对象,然后通过 throw 语句实现抛出操作(提交给 Java 运行环境)

如:IOException e = new IOException();

   throw e;

5 自定义异常类

5.1 自定义异常类引入

    (1)如果预计程序可能产生一个特定的异常问题,该问题无法用系统定义的异常情况来描述。此时根据程序的特殊逻辑,在用户程序中自定义一个异常情况类和异常对象,主要用来处理用户程序中特定的逻辑运行错误。

────────────────────────────────────────────────────────────

5.2 自定义异常类作用

    (1)用来处理程序中可能产生的特殊逻辑错误。能够被系统即使识别和处理而不扩散产生更大的影响,使用户程序具有更好的容错性,使系统更加安全稳定。

────────────────────────────────────────────────────────────

5.3 自定义异常类要求

    (1)声明一个新的异常类,作为 Exception 类或其他某个已经存在的系统异常类或其他用户异常类的子类。

    (2)定义全局变量 serialVersionUID : 唯一标识一个异常类。

    (3)为新的异常类定义属性和方法,或重载父类的属性和方法,使这些属性和方法能够体现该类所对应的错误信息

public class MyException extends RuntimeException{

static final long serialVersionUID = -7034897190766939L;

public MyException(){

}

public MyException(String msg){

super(msg);

}

}

public class ThrowException {

public static void main(String[] args) {

 Student s = new  Student();

 try{

 s.setid(-1001);

 System.out.println(s);

 }

 catch(Exception e){

 e.printStackTrace();

 }

}

}

class Student{

private int id;

public void setid(int id) throws Exception{

if(id>0){

this.id = id;

}else{

//System.out.println("输入格式错误");

//手动抛出

//throw new RuntimeException("输入格式错误");

//throw new Exception("输入格式错误");

throw new MyException("不能输入负数");

}

}

@Override

public String toString() {

return "Student [id=" + id + "]";

}

 

}

6 异常处理总结

  • 7
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值