本篇主要是记录自己所理解的Java异常处理机制(基于jdk1.7)以及怎么去处理和设计异常。还记得当初学习Java异常这块的时候都没怎么注意它的用途,以为就是简单的处理下异常,我避免程序出现这样错误就行了(当初真的很懵懂很天真)。当踏入社会工作后才知道一个好的异常处理框架是有多重要,比方说当你的项目投入使用的时候,当程序出错如何快速的定位到问题的根源(出了什么错,在哪出的错,为什么出错),这就跟你的异常处理的好坏有关了(当然离不开你的日志处理)。在有效使用异常的情况下,异常类型会回答报的什么错,异常堆栈跟踪回答在哪出的错,异常信息会回答为什么出错。所以如果设计和处理的不好,将会花费大量时间去维护(出现这样的情况公司肯定是不愿意的同时也会质疑你的能力了)。

  本篇将从下面几个方面进行记录,如果发现有错误的地方还请各位大佬们指出以便改进,谢谢。

一、Java异常结构

  首先你得明白异常是什么,为什么发生异常。通俗的讲,程序异常就是程序出现了错误,而这种错误可能是逻辑上的错误也可能是系统上的错误。在Java中把异常当做对象处理,所以我们要了解在java中有哪些可以类是用来描述异常的,它的层次结构图如下(只描述写重要的类):

二、异常分类及其常见异常类

  在java中,所有的异常都是通过Throwable类及其子类传播的(从上面层次结构图中可以看出)。根据层次关系我们依次来分析:

  • Throwable:在它下面有两个重要的子类:Error和Exception。它们两个都是重要的异常处理类,但两者分别承担的角色或者针对的对象却不一样,请看下面分析。
  • Error:是指程序无法处理的错误,也称unchecked exceptions(未经检查的异常:编译器不要求强制处置的异常)。比如:Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
  • Exception:是程序本身可以处理的异常。其中除了RuntimeException及其子类外的任何Exception子类都称为checked exceptions(受检查的异常:编译器要求必须处置的异常)。自然RuntimeException及其子类就归属于非受检查的异常。
  1. /**
  2. * The class {@code Exception} and its subclasses are a form of
  3. * {@code Throwable} that indicates conditions that a reasonable
  4. * application might want to catch.
  5. *
  6. * <p>The class {@code Exception} and any subclasses that are not also
  7. * subclasses of {@link RuntimeException} are <em>checked
  8. * exceptions</em>. Checked exceptions need to be declared in a
  9. * method or constructor's {@code throws} clause if they can be thrown
  10. * by the execution of the method or constructor and propagate outside
  11. * the method or constructor boundary.
  12. *
  13. * @author Frank Yellin
  14. * @see java.lang.Error
  15. * @jls 11.2 Compile-Time Checking of Exceptions
  16. * @since JDK1.0
  17. */
  18. public class Exception extends Throwable {

  根据上面Excepiton类还可以分成这两大类:运行时异常和非运行时异常。

  • 运行时异常:都是RuntimeException类及其子类。例如常见类:NullPointerException(空指针)、IndexOutOfBoundsException(下标越界异常)、ArithmeticException(算术异常)、ClassNotFoundException(找不到类异常)、IllegalArgumentException (非法参数异常)等。这些异常也属于非受检查异常。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
  • 非运行时异常:是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。例如常见类:IOException、SQLException、ParseException、FileNotFoundException(文件找不到异常)等。
  • 综上分类,可以将Throwable划分成这样:

三、异常处理机制

  在java中异常处理机制大致为:先抛出异常再捕捉异常。抛出异常一般是交给java虚拟机,当然也可以自己手动抛出异常(下面会涉及到),重点是怎么捕捉异常。

  1、捕获异常(try、catch、finally)

  捕获异常的形式可能是上面三个的组合,组合形式有:try..catch、try...finally和try..catch..finally

  主要记录下try..catch..finally的主要事项:

  1.1、其中catch块可以有多个,但要注意捕获异常类的顺序:子类一定要在父类前,否则会编译不通过。

  1. @Test
  2. public void test1() {
  3. int[] arr = {1,3,5,0};
  4. try{
  5. for (int i = 0; i < arr.length; i ++) {
  6. System.out.println(10/arr[i]);
  7. }
  8. }catch (Exception e){
  9. e.printStackTrace();
  10. }catch (ArithmeticException e){//编译不通过。因为异常在前面的catch块中捕获。
  11. e.printStackTrace();
  12. }finally{
  13. System.out.println("end");
  14. }
  15. }

  1.2  当catch块中有return时要注意其执行顺序:finally语句在return返回之前执行。

  1. public class ExceptionTest {
  2.  
  3. @Test
  4. public void test1() {
  5. System.out.println("计算结果:" + sum());
  6. }
  7.  
  8. public int sum() {
  9. int count = 0;
  10. int[] arr = {1,3,5,0};
  11. try{
  12. for (int i = 0; i < arr.length; i ++) {
  13. count += 10/arr[i];
  14. }
  15. }catch (ArithmeticException e){
  16. System.out.println("计算失败,分母不能为0:" + e.getMessage());
  17. return count;
  18. }finally{
  19. System.out.println("sum() end");//会先执行
  20. }
  21. return count;
  22. }
  23. }

  ouput:

  1. 计算失败,分母不能为0:/ by zero
  2. sum() end
  3. 计算结果:15

  1.3  当catch块中有return时要注意fianlly语句对其返回值进行修改时是否影响其返回值:基本类型及其字符串类型是不会被改变的,对象类型下成员变量的值是可以改变的。

  1. 1 public class ExceptionTest {
  2. 2
  3. 3 @Test
  4. 4 public void test1() {
  5. 5 System.out.println("基本类型mod1()=" + mol1());
  6. 6 System.out.println("字符串类型mod2()=" + mol2());
  7. 7 System.out.println("对象类型mod3()=" + mol3());
  8. 8 }
  9. 9
  10. 10 public int mol1() {
  11. 11 int count = 0;
  12. 12 int[] arr = {1,3,5,0};
  13. 13 try{
  14. 14 for (int i = 0; i < arr.length; i ++) {
  15. 15 arr[i] = 10/arr[i];
  16. 16 }
  17. 17 }catch (ArithmeticException e){
  18. 18 return count;
  19. 19 }finally{
  20. 20 //基本类型修改无效,其实这相当于一个局部变量
  21. 21 count = -1;
  22. 22 }
  23. 23 return count;
  24. 24 }
  25. 25
  26. 26 public String mol2() {
  27. 27 String msg = "success";
  28. 28 int[] arr = {1,3,5,0};
  29. 29 try{
  30. 30 for (int i = 0; i < arr.length; i ++) {
  31. 31 arr[i] = 10/arr[i];
  32. 32 }
  33. 33 }catch (ArithmeticException e){
  34. 34 msg = "fail";
  35. 35 return msg;
  36. 36 }finally{
  37. 37 //字符串修改无效,其实这相当于一个局部变量
  38. 38 msg = "fail, finally";
  39. 39 }
  40. 40 return msg;
  41. 41 }
  42. 42 public StringBuffer mol3() {
  43. 43 StringBuffer msg = new StringBuffer();
  44. 44 int[] arr = {1,3,5,0};
  45. 45 try{
  46. 46 for (int i = 0; i < arr.length; i ++) {
  47. 47 arr[i] = 10/arr[i];
  48. 48 }
  49. 49 }catch (ArithmeticException e){
  50. 50 msg.append("fail");
  51. 51 return msg;
  52. 52 }finally{
  53. 53 //对象类型,其成员变量char[] value;的值是可以被改变的
  54. 54 msg.append(", finally");
  55. 55 }
  56. 56 return msg;
  57. 57 }
  58. 58
  59. 59 }

  output:

  1. 基本类型mod1()=0
  2. 字符串类型mod2()=fail
  3. 对象类型mod3()=fail, finally

  1.4  当finally语句中有返回值时,会覆盖catch中的返回语句,也会使catch块的throw 抛出的异常失效。(其实不建议使用的)

  1. public class ExceptionTest {
  2.  
  3. @Test
  4. public void test1() {
  5. System.out.println("基本类型mod1()=" + mol4());
  6. System.out.println("字符串类型mod2()=" + mol5());
  7. }
  8.  
  9. public int mol4() {
  10. int count = 0;
  11. int[] arr = {1,3,5,0};
  12. try{
  13. for (int i = 0; i < arr.length; i ++) {
  14. arr[i] = 10/arr[i];
  15. }
  16. }catch (ArithmeticException e){
  17. return count;
  18. }finally{
  19. count = -1;
  20. return count;//直接返回值,不会在进入catch块中执行
  21. }
  22. }
  23.  
  24. public String mol5() {
  25. String msg = "success";
  26. int[] arr = {1,3,5,0};
  27. try{
  28. for (int i = 0; i < arr.length; i ++) {
  29. arr[i] = 10/arr[i];
  30. }
  31. }catch (ArithmeticException e){
  32. throw new ArithmeticException("分母不能为0");
  33. }finally{
  34. //字符串修改无效,其实这相当于一个局部变量
  35. msg = "fail, finally";
  36. return msg;//直接返回值,不会在进入catch块抛出异常
  37. }
  38. //return msg;
  39. }
  40. }

  output:

  1. 基本类型mod1()=-1
  2. 字符串类型mod2()=fail, finally

  2、抛出异常,有两种方式:使用throws指定异常,在方法上使用;可以使用throw new 的方法,在方法里使用。不要搞混淆就行。

四、有关设计和处理异常的几个建议(参考Effective Java)

  1、只针对异常的情况才使用异常,不要用异常去控制正常流程。(这点我想大部分人不会这么做,但是也列举出来,如果这么做了会引起莫名奇妙的问题)

  2、避免不必要的使用受检异常。

  3、优先使用标准异常,即错误信息相对应的异常,不要乱抛出异常类否则会找不到问题的根源。比方说有个地方是数组索引超限,你却抛出个参数非法异常,这样就掩盖了原始异常信息。

  4、不要忽略异常,即不要使用空catch块。(没有异常信息,就无法找出问题的所在)

  5、尽量捕获写细节信息。比方说数组索引越界,它是超过最大索引还是小于0?

Java基础(四)-异常处理机制及其设计的更多相关文章

  1. 黑马程序员——JAVA基础之异常处理机制

    ------- android培训.java培训.期待与您交流! ---------- 异常:就是程序在运行时出现不正常情况. 异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式 ...

  2. Java基础之异常处理机制

    在Java中,异常分为编译时异常和运行时异常. 编译时异常又叫编译时被监测的异常:在程序编译过程中监测到非运行时异常的异常,出现该异常要么向上抛出,要么捕获处理.运行时异常(runtimeExcept ...

  3. Java基础总结--异常处理机制

    ----异常的概述-----1.异常,就是不正常的现象,可能发生在编译期间也可能发生在运行期间2.可能会出现不同的异常,进而在Java中对其描述封装为类--在这些异常类中抽取其共性的东西(异常发生的位 ...

  4. Java中的异常处理机制的简单原理和应用?

    程序运行过程中可能出现各种"非预期"情况,这些非预期情况可能导致程序非正常结束. 为了提高程序的健壮性,Java提供了异常处理机制: try { s1... s2... s3... ...

  5. Java 中的异常处理机制

    生活中的异常:  不能够完整而顺利的完成一些工作 根据不同的异常进行相应的处理,而不会就此终端我们的生活 引出:  异常处理: 方式:  1.选择结构(逻辑判断)避免 demo:if逻辑处理异常 im ...

  6. Java基础:异常机制

    最近开始了找工作的面试,在面试过程中,面试官问了关于Java当中的异常处理机制,一直以来,无论写代码还是看书,自己对异常处理这一块就没有很好的重视过,对它的认知也仅仅停留在通过Try-catch去进行 ...

  7. 【Java基础】异常处理

    异常处理 异常概述 在 Java 语言中,将程序执行中发生的不正常情况称为"异常",但是开发过程中的语法错误和逻辑错误不是异常. 在执行过程中所发生的异常事件可分为两类: Erro ...

  8. Java中的异常处理机制《》

    异常机制已经成为判断一门编程语言是否成熟的标准,异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序健壮性. Java异常机制主要依赖于try.catch.finall ...

  9. Java面向对象编程之异常处理机制

    一:Java的异常处理机制的优点: 1:把各种不同情况的异常情况分类,使用JAVA类来表示异常情况,这种类被称为异常类.把各种异常情况表示成异常类,可以充分的发挥类的可扩展性和可重用性. 2:异常流程 ...

随机推荐

  1. kafka学习笔记2:生产者

    这次的笔记主要记录一下kafka的生产者的使用和一些重要的参数. 文中主要截图均来自kafka权威指南 主要涉及到两个类KafkaProducer和ProducerRecord. 总览 生产者的主要架 ...

  2. 【Python】Non-ASCII character '\xe6' 错误解决方法

    刚刚在写Python程序的时候遇到了一个问题,无论是在程序中什么地方出现中文字符,都会出现如下错误 SyntaxError: Non-ASCII character '\xe6' 网上查阅了一下这应该 ...

  3. Spring MVC体系结构和处理请求控制器

    Spring MVC体系结构和处理请求控制器 一:MVC设计模式: (1.)数据访问接口:DAO层 (2.)处理业务逻辑层:Service层 (3.)数据实体:POJO (4.)负责前段请求接受并处理 ...

  4. java 导出blob图片到excel

    实现功能,导出当前页面显示员工的图片,核心代码已给出,仅供参考, 如需转载请注明出处http://www.cnblogs.com/wangjianguang/p/7852060.html 随便再扯2句 ...

  5. Bash 常用快捷键(转)

    在mtysql client中按HOME键和END键失效,查了也没有找到原因 使用Bash常用的快捷方式即可. http://blog.csdn.net/mingzhou/article/detail ...

  6. [转]查询sqlserver 正在执行的sql语句的详细信息

    包含用户名,所在数据库,执行的sql语句,执行开始时间,驱动程序,主机名称 SELECT     [Spid] = session_Id, ecid, [Database] = DB_NAME(sp. ...

  7. Struts2初探

    我记得美妙的瞬间:在我的面前出现了你,有如昙花一现的幻影 今天写一篇Struts2框架的,在很久很久以前,Struts2可谓是称霸江湖,纵然现在有后起之秀,但Struts2依然可以成为老牌的主流框架, ...

  8. 关于SQLServer数据库中字段值为NULL,取出来该字段放在DataTable中,判断datatable中该字段值是否为NULL的三种方法

    1. DataTable dt;                               //假设字段为name, dt已经保存了数据dt.rows[0]["name"] == ...

  9. 一个Win32API Trace Tool的设计与实现

    用VC编程也有不短的时间了,对kernel32.advapi32.user32.gdi32等动态库里的API多数都已经很熟悉了.API是操作系统提供给应用程序的一组服务,很久以前就想要做个小工具,用来 ...

  10. C++雾中风景3:const用法的小结

    const作为C与C++共有的关键字,很多使用的方式大同小异.但由于C++是一门面向对象的语言,在类和对象中有更多的使用规则.之前学习C语言的时候就被const这个关键字搅得焦头烂额,正巧也借这篇文章 ...