- 浏览: 122406 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
zczjdyj123:
大神啊,我在tomcat定是任务里面抓取新闻,这种方式实现不了 ...
httpclient 中文乱码的解决方案 -
zczjdyj123:
str=new String(str.getBytes(),& ...
httpclient 中文乱码的解决方案 -
Ralfc:
http://tomcat.apache.org/connec ...
apache与 tomcat 集群配置与session共享 -
lengyueheiying:
我注册登录就是为了感谢你,你帮我解决了我2天没有搞定的问题谢谢 ...
httpclient 中文乱码的解决方案 -
litxuf:
------------------ 可恶的64k 2w汉字 ...
DSA签名在java与.net平台的互联互通问题
Java 语言要求 java 程序中(无论是谁写的代码),所有抛出( throw )的异常都必须是从 Throwable 派生而来。 当然,实际的 Java 编程中,由于 JDK 平台已经为我们设计好了非常丰富和完整的异常对象分类模型。因此, java 程序员一般是不需要再重新定义自己的异常对象。而且即便是需要扩展自定义的异常对象,也往往会从 Exception 派生而来。所以,对于 java 程序员而言,它一般只需要在它的顶级函数中 catch(Exception ex) 就可以捕获出所有的异常对象。 所有异常对象的根基类是 Throwable , Throwable 从 Object 直接继承而来(这是 java 系统所强制要求的),并且它实现了 Serializable 接口(这为所有的异常对象都能够轻松跨越 Java 组件系统做好了最充分的物质准备)。从 Throwable 直接派生出的异常类有 Exception 和 Error 。 Exception 是 java 程序员所最熟悉的,它一般代表了真正实际意义上的异常对象的根基类。也即是说, Exception 和从它派生而来的所有异常都是应用程序能够 catch 到的,并且可以进行异常错误恢复处理的异常类型。而 Error 则表示 Java 系统中出现了一个非常严重的异常错误,并且这个错误可能是应用程序所不能恢复的,例如 LinkageError ,或 ThreadDeath 等。
首先还是看一个例子吧!代码如下:
import java.io.*;
public class Trans
{
public static void main(String[] args)
{
try
{
BufferedReader rd=null;
Writer wr=null;
try
{
File srcFile = new File((args[0]));
File dstFile = new File((args[1]));
rd = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile), args[2]));
wr = new OutputStreamWriter(new FileOutputStream(dstFile), args[3]);
// 注意下面这条语句,它有什么问题吗?
if (rd == null || wr == null) throw new Exception("error! test!");
while(true)
{
String sLine = rd.readLine();
if(sLine == null) break;
wr.write(sLine);
wr.write("\r\n");
}
}
finally
{
wr.flush();
wr.close();
rd.close();
}
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
熟悉 java 语言的程序员朋友们,你们认为上面的程序有什么问题吗?编译能通过吗?如果不能,那么原因又是为何呢?好了,有了自己的分析和预期之后,不妨亲自动手编译一下上面的小程序,呵呵!结果确实如您所料?是的,的确是编译时报错了,错误信息如下:
E:\Trans.java:20: unreported exception java.lang.Exception; must be caught or declared to be thrown
if (rd == null || wr == null) throw new Exception("error! test!");
1 error
上面这种编译错误信息,相信 Java 程序员肯定见过(可能还是屡见不鲜!)!
相信老练一些的 Java 程序员一定非常清楚上述编译出错的原因。那就是如错误信息中(“ must be caught ”)描述的那样, 在 Java 的异常处理模型中,要求所有被抛出的异常都必须要有对应的“异常处理模块” 。也即是说,如果你在程序中 throw 出一个异常,那么在你的程序中(函数中)就必须要 catch 这个异常(处理这个异常)。例如上面的例子中,你在第 20 行代码处,抛出了一个 Exception 类型的异常,但是在该函数中,却没有 catch 并处理掉此异常的地方。因此,这样的程序即便是能够编译通过,那么运行时也是致命的(可能导致程序的崩溃),所以, Java 语言干脆在编译时就尽可能地检查(并卡住)这种本不应该出现的错误,这无疑对提高程序的可靠性大有帮助。
但是,在 Java 语言中,这就是必须的。 如果一个函数中,它运行时可能会向上层调用者函数抛出一个异常,那么,它就必须在该函数的声明中显式的注明(采用 throws 关键字) 。还记得刚才那条编译错误信息吗?“ must be caught or declared to be thrown ”,其中“ must be caught ”上面已经解释了,而后半部分呢?“ declared to be thrown ”是指何意呢?其实指的就是“必须显式地声明某个函数可能会向外部抛出一个异常”,也即是说,如果一个函数内部,它可能抛出了一种类型的异常,但该函数内部并不想(或不宜) catch 并处理这种类型的异常,此时,它就必须使用 throws 关键字来声明该函数可能会向外部抛出一个异常,以便于该函数的调用者知晓并能够及时处理这种类型的异常。下面列出了这几种情况的比较,代码如下:
// 示例程序 1 ,这种写法能够编译通过
package com.ginger.exception;
import java.io.*;
public class Trans {
public static void main(String[] args) {
try {
test();
} catch (Exception ex) {
ex.printStackTrace();
}
}
static void test() {
try {
throw new Exception("To show Exception Successed");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
// 示例程序 2 ,这种写法就不能够编译通过
import java.io.*;
public class Trans {
public static void main(String[] args) {
try {
test();
}
// 虽然这里能够捕获到 Exception 类型的异常
catch (Exception ex) {
ex.printStackTrace();
}
}
static void test() {
throw new Exception("test");
}
}
// 示例程序 3 ,这种写法又能够被编译通过
import java.io.*;
public class Trans
{
public static void main(String[] args)
{
try
{
test();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
// 由于函数声明了可能抛出 Exception 类型的异常
static void test() throws Exception
{
throw new Exception("test");
}
}
// 示例程序 4 ,它又不能够被编译通过了
import java.io.*;
public class Trans
{
public static void main(String[] args)
{
try
{
// 虽然 test() 函数并没有真正抛出一个 Exception 类型的异常
// 但是由于它函数声明时,表示它可能抛出一个 Exception 类型的异常
// 所以,这里仍然不能被编译通过。
// 呵呵!体会到了 Java 异常处理模型的严谨吧!
test();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
static void test() throws Exception
{
}
}
不知上面几个有联系的示例是否能够给大家带来“豁然开朗”的感觉,坦率的说, Java 提供的异常处理模型并不复杂,相信太多太多 Java 程序员有着比我更深刻的认识。最后,补充一种例外情况,请看如下代码:
import java.io.*;
public class Trans {
public static void main(String[] args) {
try {
test();
} catch (Exception ex) {
ex.printStackTrace();
}
}
static void test() throws Error {
throw new Error(" 故意抛出一个 Error");
}
}
朋友们!上面的程序能被编译通过吗?注意,按照刚才上面所总结出的规律:在 Java 的异常处理模型中,要求所有被抛出的异常都必须要有对应的 catch 块!那么上面的程序肯定不能被编译通过,因为 Error 和 Exception 都是从 Throwable 直接派生而来,而 test 函数声明了它可能抛出 Error 类型的异常,但在 main 函数中却并没有 catch(Error) 或 catch(Throwable) 块,所以它理当是会编译出错的!真的吗?不妨试试!呵呵!结果并非我们之预料,而它恰恰是正确编译通过了。为何? WHY ? WHY ?
其实,原因很简单,那就是因为 Error 异常的特殊性。 Java 异常处理模型中规定: Error 和从它派生而来的所有异常,都表示系统中出现了一个非常严重的异常错误,并且这个错误可能是应用程序所不能恢复的 (其实这在前面的内容中已提到过)。因此,如果系统中真的出现了一个 Error 类型的异常,那么则表明,系统已处于崩溃不可恢复的状态中,此时,作为编写 Java 应用程序的你,已经是没有必要(也没能力)来处理此等异常错误。所以, javac 编译器就没有必要来保证:“在编译时,所有的 Error 异常都有其对应的错误处理模块”。当然, Error 类型的异常一般都是由系统遇到致命的错误时所抛出的,它最后也由 Java 虚拟机所处理。而作为 Java 程序员的你,可能永远也不会考虑抛出一个 Error 类型的异常。因此 Error 是一个特例情况!
特别关注一下 RuntimeException
上面刚刚讨论了一下 Error 类型的异常处理情况, Java 程序员一般无须关注它(处理这种异常)。另外,其实在 Exception 类型的异常对象中,也存在一种比较特别的“异常”类型,那就是 RuntimeException ,虽然它是直接从 Exception 派生而来,但是 Java 编译器( javac )对 RuntimeException 却是特殊待遇,而且是照顾有加。不信,看看下面的两个示例吧!代码如下:
// 示例程序 1
// 它不能编译通过,我们可以理解
import java.io.*;
public class Trans {
public static void main(String[] args) {
test();
}
static void test() {
// 注意这条语句
throw new Exception(" 故意抛出一个 Exception");
}
}
// 示例程序 2
// 可它却为什么能够编译通过呢?
import java.io.*;
public class Trans {
public static void main(String[] args) {
test();
}
static void test() {
// 注意这条语句
throw new RuntimeException(" 故意抛出一个 RuntimeException");
}
}
对上面两个相当类似的程序, javac 编译时却遭遇了两种截然不同的处理,按理说,第 2 个示例程序也应该像第 1 个示例程序那样,编译时报错!但是 javac 编译它时,却例外地让它通过它,而且在运行时, java 虚拟机也捕获到了这个异常,并且会在 console 打印出详细的异常信息。运行结果如下:
java.lang.RuntimeException: 故意抛出一个 RuntimeException
at Trans.test(Trans.java:13)
at Trans.main(Trans.java:8)
Exception in thread "main"
为什么对于 RuntimeException 类型的异常(以及从它派生而出的异常类型), javac 和 java 虚拟机都特殊处理呢?要知道,这可是与“ Java 异常处理模型更严谨和更安全”的设计原则相抵触的呀!究竟是为何呢?这简直让人不法理解呀!
只不过, Java 语言中, RuntimeException 被统一纳入到了 Java 语言和 JDK 的规范之中。请看如下代码,来验证一下我们的理解!
import java.io.*;
public class Trans
{
public static void main(String[] args)
{
test();
}
static void test()
{
int i = 4;
int j = 0;
// 运行时,这里将触发了一个 ArithmeticException
// ArithmeticException 从 RuntimeException 派生而来
System.out.println("i / j = " + i / j);
}
}
运行结果如下:
java.lang.ArithmeticException: / by zero
at Trans.test(Trans.java:16)
at Trans.main(Trans.java:8)
Exception in thread "main"
又如下面的例子,也会产生一个 RuntimeException ,代码如下:
import java.io.*;
public class Trans
{
public static void main(String[] args)
{
test();
}
static void test()
{
String str = null;
// 运行时,这里将触发了一个 NullPointerException
// NullPointerException 从 RuntimeException 派生而来
str.compareTo("abc");
}
}
所以,针对 RuntimeException 类型的异常, javac 是无法通过编译时的静态语法检测来判断到底哪些函数(或哪些区域的代码)可能抛出这类异常(这完全取决于运行时状态,或者说运行态所决定的),也正因为如此, Java 异常处理模型中的“ must be caught or declared to be thrown ”规则也不适用于 RuntimeException (所以才有前面所提到过的奇怪编译现象,这也属于特殊规则吧)。但是, Java 虚拟机却需要有效地捕获并处理此类异常。当然, RuntimeException 也可以被程序员显式地抛出,而且为了程序的可靠性,对一些可能出现“运行时异常( RuntimeException )”的代码区域,程序员最好能够及时地处理这些意外的异常,也即通过 catch(RuntimeExcetion) 或 catch(Exception) 来捕获它们。如下面的示例程序,代码如下:
import java.io.*;
public class Trans
{
public static void main(String[] args)
{
try
{
test();
}
// 在上层的调用函数中,最好捕获所有的 Exception 异常!
catch(Exception e)
{
System.out.println("go here!");
e.printStackTrace();
}
}
// 这里最好显式地声明一下,表明该函数可能抛出 RuntimeException
static void test() throws RuntimeException
{
String str = null;
// 运行时,这里将触发了一个 NullPointerException
// NullPointerException 从 RuntimeException 派生而来
str.compareTo("abc");
}
}
发表评论
-
tomcat 连接池配置整理 (JNDI C3P0)
2013-02-18 17:54 1635简单的归纳整理一下各种几种连接池的配置方式 以便查询 ... -
(转载)Spring管理iBatis事务
2011-07-25 17:48 1447<sqlMapConfig> ... -
使Maven 2在package、install等阶段跳过运行Test的配置
2011-06-28 18:25 2049方法1:To skip running the tests f ... -
DSA签名在java与.net平台的互联互通问题(2)
2011-06-13 15:49 821//DSA JAVA平台签名转成.net可以认识的 ... -
转】eclipse快捷键 10个最有用的快捷键
2011-04-25 15:27 1481一个Eclipse骨灰级开发者总结了他认为最 ... -
设计模式——单例模式
2010-03-11 17:16 843单例模式的要点:1、某个类只能有一个实例;2、必须自行创建自己 ... -
提交多行数据到Struts的ActionForm的List属性中
2010-01-12 12:25 1674WEB 应用中一般都会处理主从表的信息, 或者称之为头层与行层 ... -
httpclient 中文乱码的解决方案
2009-08-26 12:00 7624最近写个httpclient post的方法如下 pu ... -
Unicode、UTF-8 和 ISO8859-1到底有什么区别
2009-08-17 14:44 1873Unicode、UTF-8 和 ISO8859-1 ... -
编码简介:ASCII,Unicode,UTF-8,GB2312
2009-08-17 14:25 9931. ASCII码 我们知道,在计算机内部,所有的信息最终都 ... -
JAVA-用HttpClient来模拟浏览器GET,POST
2009-03-03 10:19 2171一般的情况下我们都是使用IE或者Navigator浏览器来访问 ... -
java的移位运算
2009-02-26 13:00 1022一 基本概念 所有的整 ... -
日志操作之 log4J
2009-02-26 12:59 1044在应用程序中输出日志有有三个目的: (1)监视代码中变量的变 ... -
Java正则表达式详解
2009-02-26 12:55 814如果你曾经用过Perl或任何其他内建正则表达式支持的语言 ...
相关推荐
Java 异常机制小结 Java 异常机制是 Java 语言中一个非常重要的方面,也是程序设计的一大难点。Java 语言在设计的当初就考虑到异常处理的框架的方案,使得所有的异常都可以用一个类型来表示,不同类型的异常对应...
在静态编译器中实现Java异常机制的算法 Java 异常机制是 Java 语言中的一种重要机制,用于处理程序中的异常情况。在静态编译器中实现 Java 异常机制可以提高 Java 程序的执行效率和可靠性。下面将对在静态编译器中...
### Java异常机制详解 #### 一、Java异常机制概述 Java异常处理机制是Java语言的一个重要组成部分,用于处理程序在运行过程中可能出现的各种错误情况。它能够帮助开发者更好地控制程序流,确保程序即使遇到异常也...
【JAVA异常机制与安卓应用程序崩溃分析】 JAVA异常机制是JAVA编程中的重要组成部分,它主要用于处理程序运行时出现的错误情况。当JAVA代码中发生异常时,程序会立即停止当前流程,转而寻找合适的异常处理代码,这个...
Java异常机制是Java语言中用于处理程序运行时发生的错误的一种机制。它为错误提供了对象化的处理方式,使得程序可以更加健壮、易于维护。异常处理的核心在于能够使程序在遇到错误时不会直接崩溃,而是可以执行一段...
Java异常处理是编程中至关重要的一个环节,它用于在程序执行过程中捕获并处理错误情况。异常机制使得程序能够优雅地处理错误,而不是因为意外情况而突然终止。在这个例子中,我们将探讨如何自定义异常以及如何在Java...
对面试过程中Java异常机制总结、包括异常的分类、运行机制和实例分析等
异常机制使得异常处理代码与正常的业务逻辑得以分离,从而提高代码的可读性和维护性。 **Java异常架构** Java异常是基于`Throwable`类构建的,它是所有异常和错误的根类。`Throwable`有两个主要的子类:`Error`和`...
通过实现本文提出的Java异常机制的静态编译算法,Open64编译器可以正确编译Java程序。 栈展开是被编译器和Java虚拟机普遍使用的一种实现异常处理机制的方法。本文针对传统的栈展开算法中存在的不足,提出了一种改进的...
Java 异常机制详解 Java 异常机制是 Java 语言中的一种错误处理机制,它可以帮助开发者捕获和处理程序运行时的错误和异常。Java 异常机制包括 Error、Exception、检查异常、运行时异常、异常处理和 throws 关键字等...
14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理...
这份“Java异常学习资料”包含了丰富的资源,帮助你深入理解Java异常机制,提升代码质量。 1. **异常概述** Java异常是一种在程序执行期间发生的错误或不正常情况,它可以是编译时错误,也可以是运行时错误。Java...
Java 异常机制详解 Java 异常机制是 Java 语言中的一种错误处理机制,它允许开发者在程序中捕获和处理异常。异常机制的主要组件包括 Throwable、Error 和 Exception。 1. Throwable Throwable 是 Java 语言中最...
Java异常机制是Java编程语言中一个关键特性,它允许程序员优雅地处理程序运行时可能出现的错误情况,确保程序的稳定性和健壮性。异常(Exception)是程序执行过程中发生的问题,通常是由非法操作或者不可预见的情况...
Java内存机制是Java虚拟机(JVM)的关键组成部分,它管理着程序运行时的数据存储。在Java中,内存主要分为以下几个区域: ...正确理解和运用Java内存机制以及异常处理机制对于开发健壮、高效的Java应用程序至关重要。
### 浅析JAVA异常处理机制 #### 一、Java异常处理机制概述 异常处理是Java语言中的一个重要机制,它能够确保程序在遇到不可预料的情况时仍能维持稳定运行。异常处理主要包括三个方面:捕获异常、控制程序流程以及...
【Java异常机制】Java异常机制是Java编程中用于处理程序运行时可能出现错误的一种方式。异常是一种特殊的对象,代表了程序运行过程中的不正常状态。在Java中,异常分为两种类型:Error和Exception。Error通常表示...
自定义异常是Java异常机制中的一个重要组成部分,开发者可以根据需要定义新的异常类,继承自Exception或其子类,然后在代码中抛出并处理。异常链是处理异常的一种方式,指的是在一个异常处理的过程中,创建一个新的...
### 深入理解Java异常处理机制 #### 引言 异常处理机制是任何现代编程语言不可或缺的一部分,尤其是在像Java这样的面向对象的语言中更是如此。Java的异常处理机制旨在帮助开发者编写更健壮、更易于维护的代码。...