`
zhongxiucheng
  • 浏览: 68949 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JAVA异常的认识

阅读更多
Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。
两个子类的实例,ErrorException,通常用于指示发生了异常情况。通常,这些实例是在异常情况的上下文中新近创建的,因此包含了相关的信息(比如堆栈跟踪数据)。
Throwable 包含了其线程创建时线程执行堆栈的快照(注意:只在程序中生成一个Throwable类的实例,则在这个实例中就会生成执行堆栈的快照,在JDK1.5中可以通过getStackTrace()来获取,所以如果要在程序获取堆栈的信息这是一个好方法)。它还包含了给出有关错误更多信息的消息字符串。最后,它还可以包含 cause(原因):另一个导致此 throwable 抛出的 throwable。此 cause 设施在 1.4 版本中首次出现。它也称为异常链 设施,因为 cause 自身也会有 cause,依此类推,就形成了异常链,每个异常都是由另一个异常引起的。
导致 throwable cause 的一个理由是,抛出它的类构建在低层抽象之中,而高层操作由于低层操作的失败而失败。让低层抛出的 throwable 向外传播是一种糟糕的设计方法,因为它通常与高层提供的抽象不相关。此外,这样做将高层 API 与其实现细节关联起来,假定低层异常是经过检查的异常。抛出“经过包装的异常(我在这里理解为通过包装底层异常类,虽然异常的本质还是那个底层异常,但是它改变了表面的形象,这为上层类的设计带来了很大的灵活性”(即包含 cause 的异常)允许高层与其调用方交流失败详细信息,而不会招致上述任何一个缺点。这种方式保留了改变高层实现而不改变其 API 的灵活性(尤其是,异常集合通过其方法抛出)。
导致 throwable cause 的另一个 cause 是,抛出它的方法必须符合通用接口,而通用接口不允许方法直接抛出 cause。例如,假定持久集合符合 Collection 接口,而其持久性在 java.io 的基础上实现。假定 put 方法的内部可以抛出 IOException。实现可以与其调用方交流 IOException 的详细消息,同时通过以一种合适的未检查的异常来包装 IOException,使其符合 Collection 接口。(持久集合的规范应该指示它能够抛出这种异常。) (对于这里我是这样理解的:接口已经定义好了,该抛出哪个异常也定了,但是在实现的时候,实现类调用其它方法时抛出了接口中未定的异常,那么此时就可以通过包装来解决这个问题
Cause 可以通过两种方式与 throwable 关联起来:通过一个将 cause 看作参数的构造方法;或者通过 initCause(Throwable) 方法。对于那些希望将 cause 与其关联起来的新 throwable 类,应该提供带有 cause 的构造方法,并委托(可能间接)给一个带有 cause 的 Throwable 构造方法。例如:
try {
lowLevelOp();
} catch (LowLevelException le) {
throw new HighLevelException(le);// Chaining-aware constructor
}
因为 initCause 方法是公共的,它允许 cause 与任何 throwable 相关联,甚至包括“遗留 throwable”,它的实现提前将异常链机制的附件应用到 Throwable。例如:
try {
lowLevelOp();
} catch (LowLevelException le) {
throw (HighLevelException)
new HighLevelException().initCause(le);// Legacy constructor
}
在版本 1.4 之前,许多 throwable 有自己的非标准异常链机制( ExceptionInInitializerErrorClassNotFoundExceptionUndeclaredThrowableExceptionInvocationTargetExceptionWriteAbortedExceptionPrivilegedActionExceptionPrinterIOExceptionRemoteExceptionNamingException)。所有这些 throwable 都已经更新过,可以使用标准异常链机制,同时继续实现其“遗留”链机制,以保持兼容性。
此外,从版本 1.4 开始,许多通用的 Throwable 类(例如,ExceptionRuntimeExceptionError)都已经更新,具有带 cause 的构造方法。由于有 initCause 方法存在,这不是严格要求的,但它更方便,也更形象地委托给一个带有 cause 的构造方法。
根据惯例,Throwable 类及其子类有两个构造方法,一个不带参数,另一个带有 String 参数,此参数可用于生成详细消息。此外,这些子类很可能有与其相关联的 cause,因此也应有两个构造方法,一个带 Throwable (cause),一个带 String(详细消息)和 Throwable (cause)。
在版本 1.4 中还引入了 getStackTrace() 方法,它允许通过各种形式的 printStackTrace() 方法编程访问堆栈跟踪信息,这些信息以前只能以文本形式使用。此信息已经添加到该类的序列化表示形式,因此 getStackTrace 和 printStackTrace 将可在反序列化时获得的 throwable 上正确操作。
上面这段关于异常的说明来自JDK2,下面是它的主要方法
方法摘要
fillInStackTrace() 在异常堆栈跟踪中填充。
getCause()返回此 throwable 的 cause;如果 cause 不存在或未知,则返回 null
getLocalizedMessage()创建此 throwable 的本地化描述。
getMessage()返回此 throwable 的详细消息字符串。
getStackTrace()提供编程访问由 printStackTrace() 输出的堆栈跟踪信息
initCause(Throwablecause)将此 throwable 的 cause 初始化为指定值。
void
printStackTrace()将此 throwable 及其追踪输出至标准错误流
void
printStackTrace(PrintStreams)将此 throwable 及其追踪输出到指定的输出流。
void
printStackTrace(PrintWriters)将此 throwable 及其追踪输出到指定的 PrintWriter。
void
toString()返回此 throwable 的简短描述。
对于一个异常实例包括的三个方面:堆栈信息详细说明Cause它们究竟是什么,我想可以通过上面的的printStackTrace()方法会有一个比较感性的认识,下面是一人范例:
package zxc;
publicclass Regex {
publicstaticvoid main(String args[]) {
try {
a();
} catch(HighLevelException e) {
e.printStackTrace();
}
}
staticvoid a() throws HighLevelException {
try {
b();
} catch(MidLevelException e) {
thrownew HighLevelException("这是高层异常包装",e);
}
}
staticvoid b() throws MidLevelException {
c();
}
staticvoid c() throws MidLevelException {
try {
d();
} catch(LowLevelException e) {
thrownew MidLevelException("这是中间层异常包装",e);
}
}
staticvoid d() throws LowLevelException {
e();
}
staticvoid e() throws LowLevelException {
thrownew LowLevelException("这是底层异常");
}
}
class HighLevelException extends Exception {
HighLevelException(Throwable cause) { super(cause); }
HighLevelException(String m, Throwable cause) { super(m, cause); }
}
class MidLevelException extends Exception {
MidLevelException(Throwable cause){ super(cause); }
MidLevelException(String m, Throwable cause){ super(m, cause); }
}
class LowLevelException extends Exception {
public LowLevelException() {super(); }
public LowLevelException(String m) {super(m); }
}
这个程序在运行这后会有如下的结果:
zxc.HighLevelException: 这是高层异常包装
at zxc.Regex.a(Regex.java:38) //这是异常实例的产生地点
at zxc.Regex.main(Regex.java:29)
Caused by: zxc.MidLevelException: 这是中间层异常包装
at zxc.Regex.c(Regex.java:48) //这是异常实例的产生地点
at zxc.Regex.b(Regex.java:42)
at zxc.Regex.a(Regex.java:36)
... 1 more
Caused by: zxc.LowLevelException: 这是底层异常
at zxc.Regex.e(Regex.java:55)//这是异常实例的产生地点
at zxc.Regex.d(Regex.java:52)
at zxc.Regex.c(Regex.java:46)
... 3 more
很容易看出结果被分成三个部分:其中第一部分没有Caused by: 而后两部分有,这表示后两部分是作为Cause部分出现的,应该不难看出:上面三部分消息对应上面程序中的三个异常实例,这里所说的一“部分”消息实际指的是一个异常实例所保留的堆栈信息,在每一部分的第一行显示了异常类的全类名,紧跟着是异常的详细信息(如果有的话)。还可以看到高层的异常实例显示在上面,或者说它的堆栈信息先显示,如果系统发现此异常实例存在在Cause或者说getCause()方法并没有返回null,则系统会显示这个Cause(Throwable)的堆栈信息,依此递归类推,直到将所有堆栈信息显示完,就达到了异常产生的根源所在。
这里要注意:在显示Cause的堆栈信息的时候与非Cause的堆栈信息的有点不同,显示Cause的堆栈信息的时候,在最前面有一个Caused by: 在最后面还有一个... xxx more这里的xxx是一个正整数,它表示的含义是:表示此异常实例并没有保留所有堆栈信息,它只保留了其中的一部分,其下的那个数字就是表将此实例的堆栈信息显示完之后,在堆栈的底层中还有多少条记录。以上面的消息为例:当底层异常显示完成之后,下的数字为3表示其下还有三条堆栈记录,分别是a方法、b方法、main方法的调用记录。从中还可以得出一个规律就是每部分堆栈信息的“第一条at语句”实际就是每个异常实例产生的确切地点。
这里顺便提一下就是上面显示信息的格式:at zxc.Regex.c(Regex.java:46) 这种格式在Eclipse控制台下有一个特别功能就是可以追踪代码,我想这是Eclipse控制台观察窗提供的功能,当鼠标移到括号中的内容时会显示为手形,点击会追踪到代码所在地,在Eclipse控制台观察窗下这种输出与其它输出在格式上有些不同,它们显示为带有下划线的深蓝色文字,目前我所知道有两种字串会显示为这种格式:一种是异常的类名;另一种是(Regex.java:46) 是括号中一个java文件名后跟冒号再跟一个整数。但是据我所知后一种可以追踪代码,但是能否追踪到对应的代码要括号前面的信息是否准确,即方法的全名是否正确,以及括号中的信息是否正确(文件名与行号)。这种追踪在程序调试的时候很有用,在使用log4j日志器的时候用%l格式可以输出此信息。
分享到:
评论

相关推荐

    java异常类的学习(含题目与答案)

    比较能够容易理解java的异常类的文档,适用于初学者学习,可以初步对异常类有一个比较笼统的认识

    有效的Java异常

    火龙果软件工程技术中心 摘要Java开发人员做出的有关架构的最重要的决定之一便是如何使用Java异常模型。Java异常处理成为社区中讨论最多的话题之一。一些人认为Java语言中的已检查异常(CheckedExceptions)是一次...

    完整版 Java基础教程 Java入门教程 Java语言程序设计 第5章 方法定义及调用(共20页).ppt

    完整版 Java基础教程 Java入门教程 Java语言程序设计 第1章 认识Java(共61页).ppt 完整版 Java基础教程 Java入门教程 Java语言程序设计 第2章 变量和运算符(共41页).ppt 完整版 Java基础教程 Java入门教程 Java...

    Java 异常、线程.pdf

    研究异常,认识异常,避免异常,处理异常体现:体现的是程序的健壮性和安全! 多线程是未来高并发技术的基石,也是基础!

    高效Java异常处理机制

    Java开发人员做出的有关架构的最重要的决定之一便是如何使用Java异常模型。Java异常处理成为社区中讨论最多的话题之一。一些人认为Java语言中的已检查异常(CheckedExceptions)是一次失败的尝试。本文认为错误并不...

    DAY_13 Java常用类及异常处理.md

    该文档从简单的Java程序入手,介绍了如何产生随机数,介绍了正则表达式的关键,在...同时本文还介绍了异常的几种情况,更清晰的认识异常的处理,在工作中写出优质的代码,离不开这些细节。本文特别适合Java小白学习。

    Java语言程序设计实验指导书

    1 Java运行环境 通过在不同环境编译运行一个Java编程环境,认识Java程序结构。 2 Java语言基本语法 编写程序,练习使用Java控制结构,实现循环嵌套与选择嵌套等复杂结构。 3 对象和类 编写程序实现类和对象的操作...

    11.认识异常1

    认识异常本章目标了解异常的背景掌握异常的基本用法认识Java异常体系学会自定义异常类1. 异常的背景初识异常我们曾经的代码中已经接触了一些 "异常" 了. 例如

    精通Java:JDK、数据库系统开发Web开发(实例代码)

    第7章 Java异常处理机制 第8章 Java反射机制 第9章 数据结构与集合类 第3篇 图形用户界面 第10章 Java Swing(上) 第11章 Java Swing(下) 第12章 Applet网页小程序 第13章 图形编程 第14章 多媒体编程 第4篇 Java...

    Java开发详解.zip

    031301_【第13章:Java类集】_认识类集、Collection接口笔记.pdf 031302_【第13章:Java类集】_List接口笔记.pdf 031303_【第13章:Java类集】_LinkedList类笔记.pdf 031304_【第13章:Java类集】_Set接口笔记.pdf ...

    JAVA基础知识课件 适合初学者

    JAVA基础知识课件 适合初学者 包括 ch1 Java概述 ch2 Java基本语法 ch3 类与对象 ch4-1 继承、接口和多态 ch4-2 继承、接口和多态 ch5 常用Java类库 ...看完受益匪浅,对JAVA有新认识,大学生期末考试可90+

    java基础教学-java初级资料.zip

    第一章 认识java 第二章 java 语言语法1 第三章 java 语言语法2 第四章 java 数组 第五章 面向对象1 第六章 面向对象2 第七章 面向对象3 第八章 java常用类库1 第九章 java常用类库2 第十章 异常处理 第十一章 java...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    12.2.2 认识接口的代码组成 340 12.2.3 什么是接口 341 12.2.4 使用接口仅需一步——实现接口 342 12.2.5 接口——让类集多重类型于一身 344 12.2.6 简化recordTransport()方法 347 12.3 再探接口 349 12.3.1 ...

    java零基础入门-最新版2019(600元的课)

    在本步骤中,我们将带你逐步认识如何通过Java语言实现面向对象的三大特征继承、封装、多态,并编写具有面向对象思想的Java程序 3: Java常用工具类 在本步骤中,将会介绍最常用的Java工具类,包括异常、包装器类、...

    JAVA基础教程

    --第 1 章 认识 Java --第 2 章 简单的 Java 程序 --第 3 章 Java 基本程序设计 --第四章、数组与方法 第 2 部分 Java面向对象程序设计 •面向对象概念 •类与对象 •类的封装性、继承性、多态性 •Java 异常...

    Java_Web编程新手自学手册.pdf

    第1~6章是基础篇,讲解了认识Java,Java语法,程序控制结构,数组,面向对象,异常处理等内容;第7~12章是提高篇,讲解了搭建Java Web开发环境,HTML,和XML,JSP指令和内置对象,标签和动作指令,Servlet详解,...

Global site tag (gtag.js) - Google Analytics