异常对象都是派生于Throwable 类的一个实例。

异常层次结构简化示意图:

所有的异常都是由Throwable 继承而来,但在下一层立即分解为两个分支:Error 和 Exception

Error类层次结构描述了Java运行时系统的内部错误资源耗尽错误

Exception 层次

Exception 层次分解为两个分支: RuntimeException其他异常

RuntimeException 异常:

  1. 错误的类型转换 ClassCastException
  2. 数组访问越界 ArrayIndexOutOfBoundsException
  3. 访问null指针 NullPointerException

不是派生于 RuntimeException 异常包括:

  1. 试图在文件尾部后面读取数据
  2. 试图打开一个不存在的文件
  3. 试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在

Java语言规范将派生于 Error 异常或 RuntimeException 类的所有异常称为非受查(unchecked) 异常

所有其他的异常称为受查(checked)异常

什么时候该抛出异常 throws

  1. 调用一个抛出受查异常的方法
  2. 运行时发现错误,利用 throw 语句抛出一个受查异常
  3. 程序出现错误,如 ArrayIndexOutOfBoundsException 这样的非受查异常
  4. Java 虚拟机和运行时库出现的内部错误

子类方法中声明的受查异常并不能比超类方法中声明的异常更通用,即子类方法中可抛出更特定的异常,或者根本不抛出任何异常。特别声明:如果超类方法没有抛出任何受查异常,子类也不能抛出任何受查异常。

自定义异常:

  1. 定义一个派生于Exception的类,或者派生于Exception子类的类。
  2. 习惯上,定义的类应该包含两个构造器。一个默认的构造器,另一个是带有详细描述信息构造器。
class FileFormatException extends IOException
{public FileFormatException(){}public FileFormatException(String message){super(message);}
}
复制代码

API java.lang.Throwable

  • Throwable() 构造一个新的Throwable 对象,这个对象没有详细的描述信息
  • Throwable(String message) 构造一个新的Throwable,这个对象带有特定的详细描述信息。习惯上,所有的派生的异常类都支持一个默认的构造器和一个带有详细信息的构造器。
  • String getMessage() 获得Throwable 对象的详细描述信息

异常处理小技巧

一般异常处理最好的选择,就是将异常传递给调用者,让调用者自己去操心。

在catch 字句中可以抛出一个异常,这样做的目的是改变异常的类型。我们可以采用一种比较推荐的处理异常的方法,并且将原始异常设置为新异常的"原因":

try
{access the database
}
catch(SQLException e)
{Throwable se = new ServletException("database error");se.initCause(e);throw se;
}
复制代码

当捕获到异常时,就可以使用下面这条语句重新得到原始异常:

Throwable e = se.getCause();
复制代码

使用这种包装技术,可让用户抛出子系统中的高级异常,而不会丢失原始异常的细节

如果在一个方法中发生了一个受查异常,而不允许抛出它,那包装技术就十分有用。我们可捕获这个受查异常,并将它包装成一个运行时异常。

finally 语句

不管是否有异常被捕获,finally 字句中的代码都被执行。

当finally字句包含return 语句时,将会出现一种意想不到的结果。

假设利用return 语句从try语句块中退出。在方法返回前,finally字句的内容将被执行。如果finally字句中也有一个return语句,这个返回值将会覆盖原始的返回值。例:

 public static int f(int n)
{try{return n*n;}finally {if (2 == n)return 0;}
}
复制代码

如果调用f(2) ,try语句返回结果为4,然而在方法返回前,要执行finally字句。finally字句使得方法返回0。这个返回值覆盖了原先的返回值4。所以调用 f(2) 返回的值为 0

JAVA SE7 关闭资源的处理

待资源的try 语句(try-with-resources) 的最简形式

try(Resource res = ...)
{work with res
}
复制代码

try 块退出时,会自动调用res.close()

指定多个资源:

try(Scanner in = new Scanner(new FileInputStream("/usr/shar/dict/words"),"UTF-8");PrintWriter out = new PrintWriter("out.txt")){while (in.hasNext())out.println(in.next().toUpperCase());
}
复制代码

不管这个块如何退出,in 和 out 都会关闭。

常规方式手动编程,就需要两个嵌套的try/finally 语句。

堆栈轨迹(stack trace)

堆栈轨迹是一个方法调用过程的列表,它包含了程序执行过程中方法调用的特定位置。

访问堆栈轨迹的文本描述信息

Throwable t = new Throwable();
StackTraceElement[] frames = t.getStackTrace();
for (StackTraceElement frame : frames){analyze frame
}
复制代码

StackTraceElement 类含有能够获得文件名和当前执行的代码行号的方法。同时,还含有能够获得类名和方法名的方法。

静态的 Thread.getAllStackTrace 方法,它可以产生所有线程的堆栈轨迹。例

Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
for (Thread t : map.keySet()){StackTraceElement[] frames = map.get(t);analyze frames
}
复制代码

打印一个递归阶乘的函数的堆栈情况

public class StackTraceTest {/*** 计算n的阶乘* @param n* @return*/public static int factorial(int n){System.out.println("factorial(" + n + "):");Throwable t = new Throwable();StackTraceElement[] frames = t.getStackTrace();for (StackTraceElement f: frames)System.out.println(f);int r;if (n<=1)r =1;elser = n * factorial(n-1);System.out.println("return " + r);return r;}public static void main(String[] args){Scanner in = new Scanner(System.in);System.out.print("Enter n : ");int n = in.nextInt();factorial(n);}
}
复制代码

计算factorial(3),打印一下内容

factorial(3):
javabook.StackTraceTest.factorial(StackTraceTest.java:15)
javabook.StackTraceTest.main(StackTraceTest.java:32)
factorial(2):
javabook.StackTraceTest.factorial(StackTraceTest.java:15)
javabook.StackTraceTest.factorial(StackTraceTest.java:23)
javabook.StackTraceTest.main(StackTraceTest.java:32)
factorial(1):
javabook.StackTraceTest.factorial(StackTraceTest.java:15)
javabook.StackTraceTest.factorial(StackTraceTest.java:23)
javabook.StackTraceTest.factorial(StackTraceTest.java:23)
javabook.StackTraceTest.main(StackTraceTest.java:32)
return 1
return 2
return 6
复制代码

使用异常小技巧

异常处理不能代替简单的测试

与执行简单的测试相比,捕获异常所花费的时间大大超过前者。因此使用异常的基本规则是,旨在异常情况下使用异常机制。

不要过分地细化异常

将整个任务包装在一个try块中,这样,当任何一个操作出现问题时,整个任务都可以取消。

利用异常层次结构

  • 不要只抛出 RuntimeException 异常。应该寻找更加适当的子类或创建自己的异常类。
  • 不要只捕获Throwable 异常,否则,会使程序代码更难读、更难维护
  • 考虑受查异常和非受查异常的区别。
  • 将一种异常转换成另一种更加适合的异常时不要犹豫。

不要压制异常

在java中,往往强化地倾向关闭异常。

在检测错误时,“苛刻”要比放任更好

例如,当栈空时,Stack.pop 是要返回一个null,还是抛出一个异常?我们认为:在出错的地方抛出一个 EmptyStackException异常要比在后面抛出一个 NullPointerException 异常更好。

不要羞于传递异常

让高层次的方法通知用户发生了错误,或者放弃不成功的命令更加适宜。

5 和 6 可以归纳为“早抛出,晚捕获”。

参考

JAVA核心技术(卷1)原书第10版

Java基础 — 异常相关推荐

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

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

  2. Java基础-异常-throws Exception-抛声明

    Java基础-异常-throws Exception-抛声明 参考文章: (1)Java基础-异常-throws Exception-抛声明 (2)https://www.cnblogs.com/pl ...

  3. JAVA基础——异常详解

    阅读目录 一.异常简介 二.try-catch-finally语句 三.throw和throws关键字 四.java中的异常链 五.结束语 JAVA异常与异常处理详解 回到顶部 一.异常简介 什么是异 ...

  4. Java基础—异常分类及处理

    目录 一.概念 三.异常的处理方式 四.throw 和 throws 的区别: 一.概念 如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法.在这种情况下会抛出一个封装了错误信息的对 ...

  5. Java基础 —— 异常

    目录 异常的概念及分类 异常的处理try-catch-finally 异常抛出throw(s) 自定义异常 异常的概念及分类 什么是异常 异常是指在程序的运行过程中发生的一些不正常事件.比如:除0溢出 ...

  6. Java基础---异常---turow和throws

    异常 1.Throwable:可抛出的,是异常的顶层父类,其他的异常或者错误都是Throwable的子类类型,只有是Throwable的体系类型,才可以使用异常的处理机制 2.Error:错误,是Th ...

  7. 黑马程序员--java基础--异常(二)

    -------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iO ...

  8. Java基础-异常机制

    异常( Exception 也称例外)就是在程序的运行过程中所发生的不正常的事件,它会中 断正在运行的程序 所需文件找不到 网络连接不通或中断 算术运算错 (被零除-) 数组下标越界 装载一个不存在的 ...

  9. Java基础——异常

    异常(Exception) 基本概念 Java语言中,将程序执行中发生的不正常情况称为"异常".(开发过程中的语法错误和逻辑错误不是异常) 执行过程中所发生的异常事件可分为两大类: ...

最新文章

  1. java红黑树_JAVA学习-红黑树详解
  2. QT的QParameter类的使用
  3. spring 之 init-method InitializingBean
  4. apache php并发数,apache查看当前并发数多少
  5. python的tkinter按钮大小_如何使用python更改tkinter中按钮和帧的字体和大小?
  6. spring事务在web环境中失效的问题
  7. npm 报错 Module build failed: Error: No PostCSS Config found in:
  8. 中国量子计算机 是纠缠,量子纠缠获得突破,中国量子计算机问世,民营企业立下显著功勋...
  9. 【C语言】一些面试题。
  10. 二叉树遍历——递归算法
  11. 软考中级数据库系统工程师备考详细资料
  12. java毕业设计——基于java+JDBC+sqlserver的固定资产管理系统设计与实现(毕业论文+程序源码)——固定资产管理系统
  13. 通常环境光照度参照表
  14. 360度全景效果图制作步骤是什么?
  15. 浙江八年级 python_今年9月起,浙江八年级新增Python编程课程
  16. C#人脸识别入门篇(Step by step 人脸识别)
  17. swust oj代码+解析_1165,0284,0074,0042,1171,0026,0189,0078,0046,0077,0209,0129
  18. 基于javaweb的crm客户关系管理系统(java+springboot+echarts+freemarker+layui+mysql)
  19. HbuilderX没有管理员权限,无法安装插件
  20. 公开“英特尔多核平台编程优化大赛”优化报告及源代码

热门文章

  1. gmock学习01---Linux配置gmock
  2. NLP工程师必学技能,自然语言处理进阶手册
  3. java服务限流_Java实现系统限流
  4. mysql 允许其他主机访问权限_允许其他主机访问本机MySQL
  5. Servlet 请求处理
  6. NIO和BIO如何影响应用程序的设计-数据处理
  7. 执行SQL-MapperProxy.invoke()
  8. mybatis-逻辑翻页
  9. Nacos注册中心介绍
  10. MybatisPlus入门案例