J2EE项目异常处理

 


为什么要在J2EE项目中谈异常处理呢?可能许多java初学者都想说:“异常处理不就是try….catch…finally吗?这谁都会啊!”。笔者在初学java时也是这样认为的。
如何在一个多层的j2ee项目中定义相应的异常类?在项目中的每一层如何进行异常处理?异常何时被抛出?异常何时被记录?异常该怎么记录?何时需要把checked Exception转化成unchecked Exception,何时需要把unChecked Exception转化成checked Exception?异常是否应该呈现到前端页面?如何设计一个异常框架?
本文将就这些问题进行探讨。
1. JAVA异常处理
在面向过程式的编程语言中,我们可以通过返回值来确定方法是否正常执行。比如在一个c语言编写的程序中,如果方
法正确的执行则返回1.错误则返回0。在vb或delphi开发的应用程序中,出现错误时,我们就弹出一个消息框给用户。通过方
法的返回值我们并不能获得错误的详细信息。可能因为方法由不同的程序员编写,当同一类错误在不同的方法出现时,返回
的结果和错误信息并不一致。所以java语言采取了一个统一的异常处理机制。
什么是异常?运行时发生的可被捕获和处理的错误。在java语言中,Exception是所有异常的父类。任何异常都扩展于
Exception类。Exception就相当于一个错误类型。如果要定义一个新的错误类型就扩展一个新的Exception子类。采用异常
的好处还在于可以精确的定位到导致程序出错的源代码位置,并获得详细的错误信息。
Java异常处理通过五个关键字来实现,try,catch,throw ,throws, finally。具体的异常处理结构由try….catch….finally块
来实现。try块存放可能出现异常的java语句,catch用来捕获发生的异常,并对异常进行处理。Finally块用来清除程序中未释
放的资源。不管理try块的代码如何返回,finally块都总是被执行。
一个典型的异常处理代码:

public String getPassword(String userId)throws DataAccessException{   
		String sql = "select password from userinfo where userid='"
			+userId +"'";   
		String password = null;   
		Connection con = null;   
		Statement s = null;   
		ResultSet rs = null;   
		try{   
			con = getConnection();//获得数据连接   
			s = con.createStatement();   
			rs = s.executeQuery(sql);   
			while(rs.next()){   
				password = rs.getString(1);   
			}   
			rs.close();   
			s.close();   
		}catch(SQLException ex){   
			throw new DataAccessException(ex);   
		}finally{   
			try{   
				if(con != null){   
					con.close();   
				}   
			}catch(SQLException sqlEx){   
				throw new DataAccessException(“关闭连接失败!”,sqlEx);   
			}   
		}   
		return password;   
	} 

 

 

可以看出Java的异常处理机制具有的优势:

给错误进行了统一的分类,通过扩展Exception类或其子类来实现。从而避免了相同的错误可能在不同的方法中具有不同的错误信息。在不同的方法中出现相同的错误时,只需要throw相同的异常对象即可。

获得更为详细的错误信息。通过异常类,可以给异常更为详细,对用户更为有用的错误信息。以便于用户进行跟踪和调试程序。

把正确的返回结果与错误信息分离。降低了程序的复杂度。调用者无需要对返回结果进行更多的了解。

强制调用者进行异常处理,提高程序的质量。当一个方法声明需要抛出一个异常时,那么调用者必须使用try….catch块对异常进行处理。当然调用者也可以让异常继续往上一层抛出。

 

2. Checked 异常 还是 unChecked 异常?

Java异常分为两大类:checked 异常和unChecked 异常。所有继承java.lang.Exception 的异常都属于checked异常。所有继承java.lang.RuntimeException的异常都属于unChecked异常。

当一个方法去调用一个可能抛出checked异常的方法,必须通过try…catch块对异常进行捕获进行处理或者重新抛出。

我们看看Connection接口的createStatement()方法的声明。

public Statement createStatement() throws SQLException;

       SQLException是checked异常。当调用createStatement方法时,java强制调用者必须对SQLException进行捕获处理。

 

public String getPassword(String userId){   
	try{   
		……   
		Statement s = con.createStatement();   
		……   
	}catch(SQLException sqlEx){   
		……   
	}   
	……   
}

或者:

 

public String getPassword(String userId)throws SQLException{   
   Statement s = con.createStatement();   
}

 (当然,像Connection,Satement这些资源是需要及时关闭的,这里仅是为了说明checked 异常必须强制调用者进行捕获或继续抛出)

 

  unChecked异常也称为运行时异常,通常RuntimeException都表示用户无法恢复的异常,如无法获得数据库连接,不能打开文件等。虽然用户也可以像处理checked异常一样捕获unChecked异常。但是如果调用者并没有去捕获unChecked异常时,编译器并不会强制你那么做。

  比如一个把字符转换为整型数值的代码如下:

String str = “123”;   
int value = Integer.parseInt(str); 
parseInt的方法签名为:

 

public static int parseInt(String s) throws NumberFormatException 

 

当传入的参数不能转换成相应的整数时,将会抛出NumberFormatException。因为NumberFormatException扩展于RuntimeException,是unChecked异常。所以调用parseInt方法时无需要try…catch

 

因为java不强制调用者对unChecked异常进行捕获或往上抛出。所以程序员总是喜欢抛出unChecked异常。或者当需要一个新的异常类时,总是习惯的从RuntimeException扩展。当你去调用它些方法时,如果没有相应的catch块,编译器也总是让你通过,同时你也根本无需要去了解这个方法倒底会抛出什么异常。看起来这似乎倒是一个很好的办法,但是这样做却是远离了java异常处理的真实意图。并且对调用你这个类的程序员带来误导,因为调用者根本不知道需要在什么情况下处理异常。而checked异常可以明确的告诉调用者,调用这个类需要处理什么异常。如果调用者不去处理,编译器都会提示并且是无法编译通过的。当然怎么处理是由调用者自己去决定的。

 

       所以Java推荐人们在应用代码中应该使用checked异常。就像我们在上节提到运用异常的好外在于可以强制调用者必须对将会产生的异常进行处理。包括在《java Tutorial》等java官方文档中都把checked异常作为标准用法。

       使用checked异常,应意味着有许多的try…catch在你的代码中。当在编写和处理越来越多的try…catch块之后,许多人终于开始怀疑checked异常倒底是否应该作为标准用法了。

甚至连大名鼎鼎的《thinking in java》的作者Bruce Eckel也改变了他曾经的想法。Bruce Eckel甚至主张把unChecked异常作为标准用法。并发表文章,以试验checked异常是否应该从java中去掉。Bruce Eckel语:“当少量代码时,checked异常无疑是十分优雅的构思,并有助于避免了许多潜在的错误。但是经验表明,对大量代码来说结果正好相反”

 

============未完待续========================

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值