- 浏览: 116958 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (130)
- JUnit4学习 (0)
- Spring3.X学习 (2)
- 日记 (1)
- 文学类 (2)
- Java (15)
- Thingking In Java (11)
- org.apache.poi (4)
- XML (2)
- Log4j (1)
- Jar包收集 (2)
- ExtJs (1)
- 汇编语言 (11)
- 开发工具 (0)
- 电子书 (2)
- Oracle (6)
- Ajax (1)
- Jquery (2)
- myBatis (1)
- Spring2.5学习 (6)
- Tomcat (1)
- MyEclipse (1)
- JSP (1)
- Linux shell 脚本攻略 (7)
- Python3 (2)
- HTML5 (5)
- JavaScript (7)
- Hadoop-1.2.1 (2)
- Python2.7 (12)
- Django (3)
- 软件安装 (1)
- 高级Bash脚本编程指南 (7)
- Linux命令 (3)
- Ansible (2)
- MySQL (2)
- 病历 (1)
- 操作系统 (1)
- CSS (0)
- CSS3 (0)
- 面试题 (1)
最新评论
-
hw1287789687:
http://www.cnblogs.com/hccwu/p/ ...
Java获取真实的IP地址 -
liubey:
String ip = request.getHeader(& ...
Java获取真实的IP地址 -
bewithme:
我记得uploadify这破东西只能在chrome浏览器中才有 ...
Struts2结合Jquery.uploadify上传插件的应用 -
MrLee23:
http://mrlee23.iteye.com/admin/ ...
Struts2结合Jquery.uploadify上传插件的应用 -
crysik:
import com.eshore.ppm.model.com ...
Struts2结合Jquery.uploadify上传插件的应用
2013年7月10日 星期三 00时04分21秒
第十二章 通过异常处理错误
12.1 概念
Java的基本理念是“结构不佳的代码不能运行”
Java使用异常来提供一致的错误报告模型,使得构件能够与客户端代码可靠地沟通问题。
12.2 基本异常
异常情形(Exceptional condition)是指阻止当前方法或作用域继续执行的问题。
当抛出异常后,有几件事会随之发生:
首先:同Java中其他对象一样,将使用new在堆上创建异常对象。
然后:当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理 程序。
12.2.1 异常参数
与使用Java中的其他对象一样,我们总是使用new在堆上创建异常对象,这也伴随着存储空间的分配和构造器的使用。所以标准异常类都有两个构造器:一个默认构造器,一个棘手 字符串作为参数,以便把相关信息放入异常对象的构造器:
throw new NullPointerException("t=null");
12.3 捕获异常
要明白异常是如何被捕获的,首先理解监控区域(guarded region)的概念。
12.3.1 try块
捕获异常: try{ // }
12.3.2 异常处理程序
抛出的异常必须在某处得以处理。这个“地点”就是异常处理程序。用关键字catch表示:
try{
}catch(){
}catch(){ }
终止与恢复
异常处理理论上有两种基本模型:
1) Java支持终止模型
2) 恢复模型
12.4 创建自定义异常
程序员可以自己定义异常类来表示程序中可能会遇到的特定的问题。
要自己定义异常类,必须从已有的异常类继承,最好是选择意思相近的异常类继承。
package chapter12;
/*@name PriorityQueueDemo.java
* @describe 12.4 创建自定义异常
* @since 2013-07-10 0:45
* @author 张彪
*/
class SimpleException extends Exception{}
public class InheritingException {
public void f() throws SimpleException{
System.out.println("Throw SimpleException from f();");
throw new SimpleException();
}
public static void main(String[] args) {
InheritingException sed=new InheritingException();
try {
sed.f();
} catch (SimpleException e) {
System.out.println("Caught it !");
}
}
}
/*Throw SimpleException from f();
Caught it !*/
===============================================================================
package chapter12;
class MyException extends Exception{
public MyException(){}
public MyException(String msg){super(msg);}
}
public class FullConstructors {
public static void f()throws MyException{
System.out.println("Throwing MyException from f();");
throw new MyException();
}
public static void g()throws MyException{
System.out.println("Throwing MyException from g();");
throw new MyException("Originated in g()");
}
public static void main(String[] args) {
try {
f();
} catch (MyException e) {
e.printStackTrace(System.out);
}
try {
g();
} catch (MyException e) {
e.printStackTrace(System.out);
}
}
}
/*
Throwing MyException from f();
chapter12.MyException
at chapter12.FullConstructors.f(FullConstructors.java:11)
at chapter12.FullConstructors.main(FullConstructors.java:19)
Throwing MyException from g();
chapter12.MyException: Originated in g()
at chapter12.FullConstructors.g(FullConstructors.java:15)
at chapter12.FullConstructors.main(FullConstructors.java:24)*/
在异常处理中,调用了throwable类(Exception即从此类继承)的printStackTrace()方法。它将打印“从方法调用处直到异常抛出处”的方法调用序列。
12.4.1 异常与记录日志
使用java.util.logging工具将输出记录到日志中。
package chapter12;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Logger;
/*@name LoggingException.java
* @describe 12.4.1 异常与记录日志
* @since 2013-07-10 0:59
* @author 张彪
*/
class LoggingException extends Exception{
private static Logger logger=Logger.getLogger("LoggingException");
public LoggingException(){
StringWriter trace=new StringWriter();
printStackTrace(new PrintWriter(trace));
logger.severe(trace.toString());
}
}
public class LoggingExceptions {
public static void main(String[] args) {
try {
throw new LoggingException();
} catch (LoggingException e) {
System.out.println("Caught"+e);
}
try {
throw new LoggingException();
} catch (LoggingException e) {
System.out.println("Caught"+e);
}
}
}
/*2013-7-10 1:07:56 chapter12.LoggingException <init>
严重: chapter12.LoggingException
at chapter12.LoggingExceptions.main(LoggingExceptions.java:23)
Caughtchapter12.LoggingException
Caughtchapter12.LoggingException
2013-7-10 1:07:56 chapter12.LoggingException <init>
严重: chapter12.LoggingException
at chapter12.LoggingExceptions.main(LoggingExceptions.java:28)*/
这个Logging对象会将其输出发送到System.err。 为了产生日志记录消息,我们欲获取异常抛出处的栈轨迹。
更常见的情况是我们需要捕获和记录其他人编写的异常,异常我们必须在异常处理程序中生成日志消息。
package chapter12;
class MyException2 extends Exception{
private int x;
public MyException2(){}
public MyException2(String msg){super(msg);}
public MyException2(String msg,int x){
super(msg);
this.x=x;
}
public int val(){
return x;
}
public String getMessage(){
return "Detail Message:"+x+ " "+super.getMessage();
}
}
public class ExtraFeatures{
public static void f() throws MyException2{
System.out.println("Throwing MyException2 from f()");
throw new MyException2();
}
public static void g() throws MyException2{
System.out.println("Throwing MyException2 from g()");
throw new MyException2("Originated in g()");
}
public static void h() throws MyException2{
System.out.println("Throwing MyException2 from h()");
throw new MyException2("Originated in g()",47);
}
public static void main(String[] args) {
try {
f();
} catch (MyException2 e) {
e.printStackTrace(System.out);
}
try {
g();
} catch (MyException2 e) {
e.printStackTrace(System.out);
}
try {
h();
} catch (MyException2 e) {
e.printStackTrace(System.out);
}
}
}
12.5 异常说明
Java鼓励热门把方法可能抛出的异常告知使用此方法的客户端程序员。这是种优雅的做法。异常说明属于方法说明的一部分。紧跟在形式参数的列表后面。
异常说明使用了附加的关键字throws,后面接一个所有潜在异常类型的列表,所以方法定义可能如下:
void f() throws TooBig, TooSmall, DivZero{ // .....}
12.6 捕获所有异常
可以通过异常基类Exception来捕获异常处理程序中所有的异常。
下面展示Exception的用法:
package chapter12;
public class ExceptionMethods{
public static void main(String[] args) {
try {
throw new Exception("My Exception");
} catch (Exception e) {
System.out.println("Caught Exception");
System.out.println("e.getMessage()="+e.getMessage());
System.out.println("e.getLocalizedMessage()="+e.getLocalizedMessage());
System.out.println("toString()"+e);
System.out.println("printStackTrace()");
e.printStackTrace(System.out);
}
}
}
12.6.1 栈轨迹
printStackTrace()方法所提供的信息可以通过getStackTrace()方法直接访问。这个方法将返回一个由栈轨迹中的元素所构成的数组,其中每一个元素都表示栈中的一帧。
下面是简单演示:
package chapter12.exceptions;
/*@name WhoCalled.java
* @describe 12.6.1 栈轨迹
* @since 2013-07-13 02:45
* @author 张彪
*/
public class WhoCalled {
static void f(){
try {
throw new Exception();
} catch (Exception e) {
for(StackTraceElement t: e.getStackTrace()){
System.out.println(t.getMethodName());
}
}
}
static void g(){f();}
static void h(){g();}
public static void main(String[] args) {
f();
System.out.println("-------------------");
g();
System.out.println("-------------------");
h();
}
}
/*f
main
-------------------
f
g
main
-------------------
f
g
h
main*/
元素0是栈顶元素,并且是调用序列中的最后一个方法调用。数组中的最后一个元素和栈底是调用序列中的第一个方法调用。
12.6.2 重新抛出异常
有时候希望把刚捕获的异常重新抛出。如下:
catch (Exception e)
{
System.out.println("An exception was thrown");
throw e;
}
如下例子:
package chapter12.exceptions;
/*@name WhoCalled.java
* @describe 12.6.2 重新抛出异常
* @since 2013-07-13 03:09
* @author 张彪
*/
public class ReThrowing {
public static void f() throws Exception{
System.out.println("originating the exception in f()");
throw new Exception("thrown from f()");
}
public static void g() throws Exception{
try {
f();
} catch (Exception e) {
System.out.println("Inside g(),e.printStackTrace()");
e.printStackTrace(System.out);
throw e;
}
}
public static void h() throws Exception{
try {
f();
} catch (Exception e) {
System.out.println("Inside h(),e.printStackTrace()");
e.printStackTrace(System.out);
throw (Exception)e.fillInStackTrace();
}
}
public static void main(String[] args) {
try {
g();
} catch (Exception e) {
System.out.println("main:printStackTrace()");
e.printStackTrace(System.out);
}
System.out.println("---------");
try {
h();
} catch (Exception e) {
System.out.println("main:printStackTrace()");
e.printStackTrace(System.out);
}
}
}
调用fillInStackTrace()的那一行就成了异常的新发生地了。即原来的异常发生点信息丢失了,剩下的是与新的抛出点有关的信息。
永远不必为清理一个异常而担心,他们都是用New在堆上创建的对象,所以垃圾回收器会自动把他们清理掉。
12.6.3 异常链
12.7 Java标准异常
Throwable这个Java类被用来表示任何可以作为异常被抛出的类。 分为Error 和Exception。
12.7.1 RunException
运行时异常会自动被Java虚拟机抛出
如果RunException没有被捕获而直达main()方法,那么在程序退出前将调用异常的printStackTrace()方法。
12.8 使用finally进行清理
如果希望无论try块中的异常是否抛出,它们都能得到执行,那么可以在异常处理程序后面加上finally子句。
try{}
catch(){}
finaly{}
可以将try块放在循环中,这样就建立了一个“程序继续执行之前必须要达到”的条件。
12.8.1 finally用来做什么
当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句。
12.8.2 在return中使用finally
package chapter12.exceptions;
/*@name MultipleReturn.java
* @describe 12.8.2 在return中使用finally
* @since 2013-07-28 10:27
* @author 张彪
*/
public class MultipleReturn {
public static void f(int i){
System.out.println("Initialization that requires cleanup");
try {
System.out.println("Point 1");
if(i==1) return;
System.out.println("Point 2");
if(i==2) return;
System.out.println("Point 3");
if(i==3) return;
System.out.println("Point 4");
if(i==4) return;
} finally {
System.out.println("Performing cleanup");
}
}
public static void main(String[] args) {
for (int i = 1; i < 4; i++) {
MultipleReturn.f(i);
}
}
}
/*Initialization that requires cleanup
Point 1
Performing cleanup
Initialization that requires cleanup
Point 1
Point 2
Performing cleanup
Initialization that requires cleanup
Point 1
Point 2
Point 3
Performing cleanup*/
可以发现finally中的方法会在return之前被执行。
12.8.3 缺憾:异常丢失
用某些特殊方法使用finally子句时,有些异常可以轻易的被忽略掉。
package chapter12.exceptions;
class VeryImportantExcepton extends Exception{
public String toString(){
return "A very impotant exception";
}
}
class HoHumException extends Exception{
public String toString(){
return "A trivial exception";
}
}
public class LostMessage {
void f() throws VeryImportantExcepton{
throw new VeryImportantExcepton();
}
void dispose() throws HoHumException{
throw new HoHumException();
}
public static void main(String[] args) {
try{
LostMessage ls=new LostMessage();
try{
ls.f();
}finally{
ls.dispose();
}
}catch (Exception e) {
System.out.println(e);
}
}
}
/*A trivial exception*/
从打印出的信息可以看出VeryImportantExcepton不见了。
一种更加简单丢失异常的方式是从finally中返回:
public class Exceptionilencer {
public static void main(String[] args) {
try {
throw new RuntimeException();
} finally{
//using 'return' inside the finally block will slience any thrown exception
return;
}
}
}
12.9 异常限制
当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。
12.10 构造器
如果构造器内抛出了异常,这些清理行为也许就不能正常工作了。这意味着写构造器时要格外细心。
package chapter12.exceptions;
/*@name CleanupIdioom.java
* @describe 12.10 构造器 ,注意构造器时异常的处理
* @since 2013-08-01 20:15
* @author 张彪
*/
class NeedCleanup{
private static long counter=1;
private final long id=counter++;
public void dispose(){
System.out.println("NeedCleanup "+id+" dispose");
}
}
class ConstructionException extends Exception{}
class NeedCleanup2 extends NeedCleanup{
public NeedCleanup2() throws ConstructionException{}
}
public class CleanupIdioom {
public static void main(String[] args) {
NeedCleanup nc1=new NeedCleanup();
try {
}finally {
nc1.dispose();
}
//select2
NeedCleanup nc2=new NeedCleanup();
NeedCleanup nc3=new NeedCleanup();
try{
}finally{
nc3.dispose();
nc2.dispose();
}
//select3
try {
NeedCleanup2 nc4= new NeedCleanup2();
try {
NeedCleanup2 nc5= new NeedCleanup2();
} finally{
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
12.11 异常匹配
抛出异常时,异常处理系统会按照代码的书写顺序找出“最近”的处理程序。找到后,将不再继续查找。
派生类的对象也可以匹配其基类的处理程序。
package chapter12.exceptions;
class Annoyance extends Exception{}
class Sneeze extends Annoyance{}
public class Human {
public static void main(String[] args) {
try {
throw new Sneeze();
} catch (Sneeze s) {
System.out.println("Caught Sneeze");
}catch (Annoyance a) {
System.out.println("Caught Annoyance1");
}
try {
throw new Sneeze();
} catch (Annoyance e) {
System.out.println("Caught Annoyance2");
}
}
}
/*Caught Sneeze
Caught Annoyance2*/
//如果把捕获基类的catch子句放在最前面,依次想把派生类的异常给“屏蔽”掉,就像这样:
try {
throw new Sneeze();
} catch (Annoyance s) {
System.out.println("Caught Sneeze");
}catch (Sneeze a) {
System.out.println("Caught Annoyance1");
}
}
这样编译器会发现Sneeze的catch子句永远也得不到执行,因此它会向你报告错误。
12.12 其它可选方式
事实上,异常处理的一个重要目标是将错误处理的代码和错误发生的地点相分离。
“被检查的异常”及其并发症,以及采用什么方法解决该问题。
12.12.1 历史
12.12.2 观点
12.12.3 把异常传递给控制台
12.12.4 把“被检查的异常”转换为“不检查的异常”
12.13 异常使用指南
12.14 总结
2013-08-01 21:02 记 @jinrongdajie31.xichengqu.beijing
是的! 本人初学,谢谢指点!
第十二章 通过异常处理错误
12.1 概念
Java的基本理念是“结构不佳的代码不能运行”
Java使用异常来提供一致的错误报告模型,使得构件能够与客户端代码可靠地沟通问题。
12.2 基本异常
异常情形(Exceptional condition)是指阻止当前方法或作用域继续执行的问题。
当抛出异常后,有几件事会随之发生:
首先:同Java中其他对象一样,将使用new在堆上创建异常对象。
然后:当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理 程序。
12.2.1 异常参数
与使用Java中的其他对象一样,我们总是使用new在堆上创建异常对象,这也伴随着存储空间的分配和构造器的使用。所以标准异常类都有两个构造器:一个默认构造器,一个棘手 字符串作为参数,以便把相关信息放入异常对象的构造器:
throw new NullPointerException("t=null");
12.3 捕获异常
要明白异常是如何被捕获的,首先理解监控区域(guarded region)的概念。
12.3.1 try块
捕获异常: try{ // }
12.3.2 异常处理程序
抛出的异常必须在某处得以处理。这个“地点”就是异常处理程序。用关键字catch表示:
try{
}catch(){
}catch(){ }
终止与恢复
异常处理理论上有两种基本模型:
1) Java支持终止模型
2) 恢复模型
12.4 创建自定义异常
程序员可以自己定义异常类来表示程序中可能会遇到的特定的问题。
要自己定义异常类,必须从已有的异常类继承,最好是选择意思相近的异常类继承。
package chapter12;
/*@name PriorityQueueDemo.java
* @describe 12.4 创建自定义异常
* @since 2013-07-10 0:45
* @author 张彪
*/
class SimpleException extends Exception{}
public class InheritingException {
public void f() throws SimpleException{
System.out.println("Throw SimpleException from f();");
throw new SimpleException();
}
public static void main(String[] args) {
InheritingException sed=new InheritingException();
try {
sed.f();
} catch (SimpleException e) {
System.out.println("Caught it !");
}
}
}
/*Throw SimpleException from f();
Caught it !*/
===============================================================================
package chapter12;
class MyException extends Exception{
public MyException(){}
public MyException(String msg){super(msg);}
}
public class FullConstructors {
public static void f()throws MyException{
System.out.println("Throwing MyException from f();");
throw new MyException();
}
public static void g()throws MyException{
System.out.println("Throwing MyException from g();");
throw new MyException("Originated in g()");
}
public static void main(String[] args) {
try {
f();
} catch (MyException e) {
e.printStackTrace(System.out);
}
try {
g();
} catch (MyException e) {
e.printStackTrace(System.out);
}
}
}
/*
Throwing MyException from f();
chapter12.MyException
at chapter12.FullConstructors.f(FullConstructors.java:11)
at chapter12.FullConstructors.main(FullConstructors.java:19)
Throwing MyException from g();
chapter12.MyException: Originated in g()
at chapter12.FullConstructors.g(FullConstructors.java:15)
at chapter12.FullConstructors.main(FullConstructors.java:24)*/
在异常处理中,调用了throwable类(Exception即从此类继承)的printStackTrace()方法。它将打印“从方法调用处直到异常抛出处”的方法调用序列。
12.4.1 异常与记录日志
使用java.util.logging工具将输出记录到日志中。
package chapter12;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Logger;
/*@name LoggingException.java
* @describe 12.4.1 异常与记录日志
* @since 2013-07-10 0:59
* @author 张彪
*/
class LoggingException extends Exception{
private static Logger logger=Logger.getLogger("LoggingException");
public LoggingException(){
StringWriter trace=new StringWriter();
printStackTrace(new PrintWriter(trace));
logger.severe(trace.toString());
}
}
public class LoggingExceptions {
public static void main(String[] args) {
try {
throw new LoggingException();
} catch (LoggingException e) {
System.out.println("Caught"+e);
}
try {
throw new LoggingException();
} catch (LoggingException e) {
System.out.println("Caught"+e);
}
}
}
/*2013-7-10 1:07:56 chapter12.LoggingException <init>
严重: chapter12.LoggingException
at chapter12.LoggingExceptions.main(LoggingExceptions.java:23)
Caughtchapter12.LoggingException
Caughtchapter12.LoggingException
2013-7-10 1:07:56 chapter12.LoggingException <init>
严重: chapter12.LoggingException
at chapter12.LoggingExceptions.main(LoggingExceptions.java:28)*/
这个Logging对象会将其输出发送到System.err。 为了产生日志记录消息,我们欲获取异常抛出处的栈轨迹。
更常见的情况是我们需要捕获和记录其他人编写的异常,异常我们必须在异常处理程序中生成日志消息。
package chapter12;
class MyException2 extends Exception{
private int x;
public MyException2(){}
public MyException2(String msg){super(msg);}
public MyException2(String msg,int x){
super(msg);
this.x=x;
}
public int val(){
return x;
}
public String getMessage(){
return "Detail Message:"+x+ " "+super.getMessage();
}
}
public class ExtraFeatures{
public static void f() throws MyException2{
System.out.println("Throwing MyException2 from f()");
throw new MyException2();
}
public static void g() throws MyException2{
System.out.println("Throwing MyException2 from g()");
throw new MyException2("Originated in g()");
}
public static void h() throws MyException2{
System.out.println("Throwing MyException2 from h()");
throw new MyException2("Originated in g()",47);
}
public static void main(String[] args) {
try {
f();
} catch (MyException2 e) {
e.printStackTrace(System.out);
}
try {
g();
} catch (MyException2 e) {
e.printStackTrace(System.out);
}
try {
h();
} catch (MyException2 e) {
e.printStackTrace(System.out);
}
}
}
12.5 异常说明
Java鼓励热门把方法可能抛出的异常告知使用此方法的客户端程序员。这是种优雅的做法。异常说明属于方法说明的一部分。紧跟在形式参数的列表后面。
异常说明使用了附加的关键字throws,后面接一个所有潜在异常类型的列表,所以方法定义可能如下:
void f() throws TooBig, TooSmall, DivZero{ // .....}
12.6 捕获所有异常
可以通过异常基类Exception来捕获异常处理程序中所有的异常。
下面展示Exception的用法:
package chapter12;
public class ExceptionMethods{
public static void main(String[] args) {
try {
throw new Exception("My Exception");
} catch (Exception e) {
System.out.println("Caught Exception");
System.out.println("e.getMessage()="+e.getMessage());
System.out.println("e.getLocalizedMessage()="+e.getLocalizedMessage());
System.out.println("toString()"+e);
System.out.println("printStackTrace()");
e.printStackTrace(System.out);
}
}
}
12.6.1 栈轨迹
printStackTrace()方法所提供的信息可以通过getStackTrace()方法直接访问。这个方法将返回一个由栈轨迹中的元素所构成的数组,其中每一个元素都表示栈中的一帧。
下面是简单演示:
package chapter12.exceptions;
/*@name WhoCalled.java
* @describe 12.6.1 栈轨迹
* @since 2013-07-13 02:45
* @author 张彪
*/
public class WhoCalled {
static void f(){
try {
throw new Exception();
} catch (Exception e) {
for(StackTraceElement t: e.getStackTrace()){
System.out.println(t.getMethodName());
}
}
}
static void g(){f();}
static void h(){g();}
public static void main(String[] args) {
f();
System.out.println("-------------------");
g();
System.out.println("-------------------");
h();
}
}
/*f
main
-------------------
f
g
main
-------------------
f
g
h
main*/
元素0是栈顶元素,并且是调用序列中的最后一个方法调用。数组中的最后一个元素和栈底是调用序列中的第一个方法调用。
12.6.2 重新抛出异常
有时候希望把刚捕获的异常重新抛出。如下:
catch (Exception e)
{
System.out.println("An exception was thrown");
throw e;
}
如下例子:
package chapter12.exceptions;
/*@name WhoCalled.java
* @describe 12.6.2 重新抛出异常
* @since 2013-07-13 03:09
* @author 张彪
*/
public class ReThrowing {
public static void f() throws Exception{
System.out.println("originating the exception in f()");
throw new Exception("thrown from f()");
}
public static void g() throws Exception{
try {
f();
} catch (Exception e) {
System.out.println("Inside g(),e.printStackTrace()");
e.printStackTrace(System.out);
throw e;
}
}
public static void h() throws Exception{
try {
f();
} catch (Exception e) {
System.out.println("Inside h(),e.printStackTrace()");
e.printStackTrace(System.out);
throw (Exception)e.fillInStackTrace();
}
}
public static void main(String[] args) {
try {
g();
} catch (Exception e) {
System.out.println("main:printStackTrace()");
e.printStackTrace(System.out);
}
System.out.println("---------");
try {
h();
} catch (Exception e) {
System.out.println("main:printStackTrace()");
e.printStackTrace(System.out);
}
}
}
调用fillInStackTrace()的那一行就成了异常的新发生地了。即原来的异常发生点信息丢失了,剩下的是与新的抛出点有关的信息。
永远不必为清理一个异常而担心,他们都是用New在堆上创建的对象,所以垃圾回收器会自动把他们清理掉。
12.6.3 异常链
12.7 Java标准异常
Throwable这个Java类被用来表示任何可以作为异常被抛出的类。 分为Error 和Exception。
12.7.1 RunException
运行时异常会自动被Java虚拟机抛出
如果RunException没有被捕获而直达main()方法,那么在程序退出前将调用异常的printStackTrace()方法。
12.8 使用finally进行清理
如果希望无论try块中的异常是否抛出,它们都能得到执行,那么可以在异常处理程序后面加上finally子句。
try{}
catch(){}
finaly{}
可以将try块放在循环中,这样就建立了一个“程序继续执行之前必须要达到”的条件。
12.8.1 finally用来做什么
当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句。
12.8.2 在return中使用finally
package chapter12.exceptions;
/*@name MultipleReturn.java
* @describe 12.8.2 在return中使用finally
* @since 2013-07-28 10:27
* @author 张彪
*/
public class MultipleReturn {
public static void f(int i){
System.out.println("Initialization that requires cleanup");
try {
System.out.println("Point 1");
if(i==1) return;
System.out.println("Point 2");
if(i==2) return;
System.out.println("Point 3");
if(i==3) return;
System.out.println("Point 4");
if(i==4) return;
} finally {
System.out.println("Performing cleanup");
}
}
public static void main(String[] args) {
for (int i = 1; i < 4; i++) {
MultipleReturn.f(i);
}
}
}
/*Initialization that requires cleanup
Point 1
Performing cleanup
Initialization that requires cleanup
Point 1
Point 2
Performing cleanup
Initialization that requires cleanup
Point 1
Point 2
Point 3
Performing cleanup*/
可以发现finally中的方法会在return之前被执行。
12.8.3 缺憾:异常丢失
用某些特殊方法使用finally子句时,有些异常可以轻易的被忽略掉。
package chapter12.exceptions;
class VeryImportantExcepton extends Exception{
public String toString(){
return "A very impotant exception";
}
}
class HoHumException extends Exception{
public String toString(){
return "A trivial exception";
}
}
public class LostMessage {
void f() throws VeryImportantExcepton{
throw new VeryImportantExcepton();
}
void dispose() throws HoHumException{
throw new HoHumException();
}
public static void main(String[] args) {
try{
LostMessage ls=new LostMessage();
try{
ls.f();
}finally{
ls.dispose();
}
}catch (Exception e) {
System.out.println(e);
}
}
}
/*A trivial exception*/
从打印出的信息可以看出VeryImportantExcepton不见了。
一种更加简单丢失异常的方式是从finally中返回:
public class Exceptionilencer {
public static void main(String[] args) {
try {
throw new RuntimeException();
} finally{
//using 'return' inside the finally block will slience any thrown exception
return;
}
}
}
12.9 异常限制
当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。
12.10 构造器
如果构造器内抛出了异常,这些清理行为也许就不能正常工作了。这意味着写构造器时要格外细心。
package chapter12.exceptions;
/*@name CleanupIdioom.java
* @describe 12.10 构造器 ,注意构造器时异常的处理
* @since 2013-08-01 20:15
* @author 张彪
*/
class NeedCleanup{
private static long counter=1;
private final long id=counter++;
public void dispose(){
System.out.println("NeedCleanup "+id+" dispose");
}
}
class ConstructionException extends Exception{}
class NeedCleanup2 extends NeedCleanup{
public NeedCleanup2() throws ConstructionException{}
}
public class CleanupIdioom {
public static void main(String[] args) {
NeedCleanup nc1=new NeedCleanup();
try {
}finally {
nc1.dispose();
}
//select2
NeedCleanup nc2=new NeedCleanup();
NeedCleanup nc3=new NeedCleanup();
try{
}finally{
nc3.dispose();
nc2.dispose();
}
//select3
try {
NeedCleanup2 nc4= new NeedCleanup2();
try {
NeedCleanup2 nc5= new NeedCleanup2();
} finally{
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
12.11 异常匹配
抛出异常时,异常处理系统会按照代码的书写顺序找出“最近”的处理程序。找到后,将不再继续查找。
派生类的对象也可以匹配其基类的处理程序。
package chapter12.exceptions;
class Annoyance extends Exception{}
class Sneeze extends Annoyance{}
public class Human {
public static void main(String[] args) {
try {
throw new Sneeze();
} catch (Sneeze s) {
System.out.println("Caught Sneeze");
}catch (Annoyance a) {
System.out.println("Caught Annoyance1");
}
try {
throw new Sneeze();
} catch (Annoyance e) {
System.out.println("Caught Annoyance2");
}
}
}
/*Caught Sneeze
Caught Annoyance2*/
//如果把捕获基类的catch子句放在最前面,依次想把派生类的异常给“屏蔽”掉,就像这样:
try {
throw new Sneeze();
} catch (Annoyance s) {
System.out.println("Caught Sneeze");
}catch (Sneeze a) {
System.out.println("Caught Annoyance1");
}
}
这样编译器会发现Sneeze的catch子句永远也得不到执行,因此它会向你报告错误。
12.12 其它可选方式
事实上,异常处理的一个重要目标是将错误处理的代码和错误发生的地点相分离。
“被检查的异常”及其并发症,以及采用什么方法解决该问题。
12.12.1 历史
12.12.2 观点
12.12.3 把异常传递给控制台
12.12.4 把“被检查的异常”转换为“不检查的异常”
12.13 异常使用指南
12.14 总结
2013-08-01 21:02 记 @jinrongdajie31.xichengqu.beijing
- chapter12.rar (6.7 KB)
- 下载次数: 0
评论
2 楼
listen-raining
2013-08-20
freezingsky 写道
异常虽好,但永远不要想着用异常来控制流程。应该把这句话加上去。
是的! 本人初学,谢谢指点!
1 楼
freezingsky
2013-08-01
异常虽好,但永远不要想着用异常来控制流程。应该把这句话加上去。
发表评论
-
第十三章 字符串
2013-08-06 00:50 9062013年8月1日 星期四 21时05分59秒 第十三章 字 ... -
第十一章 持有对象
2013-07-09 00:49 9272013年6月24日 星期一 20时57分09秒 第十一章 ... -
第十四章 类型信息
2013-07-02 01:26 9152013年6月25日 星期二 23时12分42秒 第十四章 ... -
第十章 内部类
2013-06-24 20:47 9662013年6月23日 星期日 16时50分56秒 第十章 内 ... -
第九章 接口
2013-06-23 16:46 8412013年6月20日 星期四 21时41分40秒 第九章 接 ... -
第八章 多态
2013-06-19 23:06 6742013年6月17日 星期一 23 ... -
Thinking in Java Fourth Edition Source Code
2013-06-17 23:10 490Thinking in Java F ... -
第七章 复用类
2013-06-17 22:36 5512013年6月16日 星期日 21时06分54秒 第七章 复 ... -
第六章 访问权限控制
2013-06-16 21:05 8452013年6月16日 星期日 11时10分46秒 第六章 访 ... -
第五章 初始化与清理
2013-06-16 10:58 5972013年6月15日 星期六 16 ...
相关推荐
Java编程思想第十二章通过异常处理错误.pptx
Java高级程序设计(第二版)--第2章-异常处理全文共19页,当前为第12页。 知识点:自定义异常、throw关键字 一、自定义异常 <class> <自定义异常类名> <extends> <Exception>{ // 变量、构造方法、成员方法 } 二、...
C#入门ppt,一共16章
由于上传文件大小限制...第12章 通过异常处理错误 第13章 字符串 第14章 类型信息 第15章 泛型 第16章 数组 第17章 容器深入研究 第18章 Java I/O系统 第19章 枚举类型 第20章 注解 第21章 并发 第22章 图形化用户界面
非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 第7章 复用类 第8章 多态 第9章 接口 第10章 内部类 第11章 持有对象 第12章 通过异常处理错误 第13章 字符串 第...
第12章 错误异常和错误处理 第13章 浮点运算 第14章 调试和跟踪特性 第15章 Keil ARM微控制器开发套件入门 第16章 IAR Embedded Workbench for ARM入门 第17章 GCC入门 第18章 输入和输出软件实例 第19章 使用嵌入式...
第12章 日期和时间 第13章 PHP 5.1 第14章 表单和导航提示 第15章 处理文件上传 第16章 网络 第17章 PHP和LDAP 第18章 会话处理器 第19章 用Smarty模板化 第20章 Web服务 第21章 安全PHP编程 第22章 SQLite 第23章 ...
通过异常处理错误 第13章 字符串 第14章 类型信息 第15章 泛型 第16章 数组 第17章 容器深入研究 第18章 Java I/O系统 第19章 枚举类型 第20章 注解 第21章 并发 第22章 图形化用户界面 水平有限,发现错误不适者,...
第一章PHP简介及环境配置.ppt 第二章PHP的基本语法.ppt 第三章其他操作符与表达式、流程控制.ppt 第四章字符串处理.ppt ...第十二章面向对象II.ppt 第十三章面向对象的数据库操作.ppt 第十四章错误和异常.ppt
第1章 计算机系统漫游 第一部分 程序结构和执行 第2章 信息的表示和处理 第3章 程序的机器级表示 第4章 处理器体系结构 第5章 优化程序性能 ... 第12章 并发编程 附录a 错误处理 参考文献
第12章 实现继承 第13章 管理数组和字符串 第14章 多态 第2周复习 第3周课程简介 第15章 特殊类和函数 第16章 高级继承 第17章 处理流 第18章 创建和使用名称空间 第19章 模板 第20章 处理错误和异常 第21...
PEAR 第12章 日期和时间 第13章 PHP 5.1<br>第14章 表单和导航提示 第15章 处理文件上传 第16章 网络 第17章 PHP和LDAP 第18章 会话处理器 第19章 用Smarty模板化 第20章 Web服务 第21章...
第3章 对象、类型和值 第4章 计算 第5章 错误 第6章 编写一个程序 第7章 完成一个程序 第8章 函数相关的技术细节 第9章 类相关的技术细节 第二部分 输入和输出 第10章 输入/输出流 第11章 定制输入/输出 第12章 一...
第3章 对象、类型和值 第4章 计算 第5章 错误 第6章 编写一个程序 第7章 完成一个程序 第8章 函数相关的技术细节 第9章 类相关的技术细节 第二部分 输入和输出 第10章 输入/输出流 第11章 定制输入/输出 第12章 一...
第8 章 错误和异常处理 134 第9 章 字符串和正则表达式 146 第10 章 处理文件和操作系统 176 第11 章 pear 197 第12 章 日期和时间 205 第13 章 处理html 表单 219 第14 章 身份验证 231 第15 章 处理文件上传 244 ...
第一篇 JavaScript入门篇 第1章 初步了解JavaScript ...第12章 JavaScript与Ajax技术 第13章 JavaScript错误与异常处理 第三篇 JavaScript实例篇 第14章 JavaScript与插件通信 第15章 JavaScript常用特效收集
第12章 图形用户界面 第13章 图形绘制 第14章 (1)Math、random、日期时间模块 第14章 (2)Numpy科学计算与matplotlib可视化 第15章 字符串、正则表达式、网络爬虫 第16章 文件和数据交换 第17章 数据库访问 第18章 ...
第12章 一个显示模型 第13章 图形类 第14章 设计图形类 第15章 绘制函数图和数据图 第16章 图形用户界面 第三部分 数据结构和算法 第17章 向量和自由空间 第18章 向量和数组 第19章 向量、模板和异常 第20章 容器和...
第12章 编写程序技巧 150 第三篇 面向对象的程序设计 第13章 初识对象 163 第14章 再识对象 169 第15章 造物者与毁灭者——对象生灭 178 第16章 共有财产·好朋友·操作符 206 第17章父与子——继承 228...