java学习笔记:java异常处理机制
发表于: java | 作者: darkmi | 日期: 2008/12/20 03:12
标签: exception,java异常
java异常概述
在运行过程中,应用程序可能遇到各种严重程度不同的错误,比如访问不存在的文件、数组访问越界等。如果程序对可能发生的错误一点不做检查,那么程序将变得容易崩溃而且很难定位到问题出现的位置;而如果在执行下一语句之前,对每个方法调用都检查所有可能的错误,那么,程序就会变得难以理解。
java的异常处理机制很和谐的解决了这一矛盾命题。
==========================
java异常相关的5个关键字
try 捕获异常
catch 处理异常
finally 有没有异常都执行
throw 抛出一个异常对象
throws 声明一个异常可能被抛出
其中:
throw用来抛出异常:
throw expression;
而throws则用来声明方法可以抛出的异常,需要注意如下两点:
(1)方法能够抛出的检查型异常用throws子句声明,它后面可以是带用逗号隔开的一系列异常类型。
(2)throws子句的约定是严格强制性的,只能抛出throws子句声明的异常类型。抛出其他类型的异常是非法的,不管是直接利用throw,还是调用别的方法间接的抛出。如果方法没有throws子句,这意味着它不能抛出人恶化检查型异常,而不是说它它可以抛出任何类型的异常。
==========================
java异常常用的两个结构
java异常的捕获(Try/Catch/Finally)
try{
somethingDangerous();
}catch ( IOException e ){
System.out.println( "oh oh" );
throw new BadDataException();
}
finally{
file.close(); // always executed
}
java异常的上抛(Try/Catch/Throw)
public class Test extends StandardTest{
public static void main (String [] args){
try{
dangerMethod();
}
catch ( StrangeException e ){
System.out.println( "oops" + e.getMessage() );
}
} // end main
void dangerMethod() throws StrangeException{
if ( unexpected() ) throw new StrangeException ( "oh oh" );
} // end dangerMethod
} // end class Test
以上两个示例的引用地址:http://mindprod.com/jgloss/jcheat.html#TRY
==========================
一篇不错的java异常文章。
1:finally 区域内的代码块在 return 之前被执行
由于 Java 程序中,所有的对象都是在堆上( Heap )分配存储空间的,这些空间完全由垃圾回收机制来对它们进行管理。因此,从这一点可以分析得出一个推论: Java 中的异常处理模型的实现,其实要比 C++ 异常处理模型简单得多。例如,它首先不需要像 C++ 异常处理模型中那样,必须要跟踪栈上的每一个“对象”的构造和析构过程(只有跟踪并掌握了这些信息,发生异常时, C++ 系统它才会知道当前应该析构销毁哪些对象呀!),这是因为 Java 程序中,栈上是绝对没有“对象”的(实际只是对堆上对象的引用)。另外,还有 Java 语言中的异常对象的传递也更为简单和容易了,它只需传递一个引用指针而已,而完全不用考虑异常对象的构造、复制和销毁过程。
当然, Java 异常处理模型较 C++ 异常处理模型复杂的地方是,它引入了 finally 机制(主要用于数据库连接的关闭、 Socket 关闭、文件流的关闭等)。其实,我们也知道 finally 语法最早是在微软的 SEH 所设计出的一种机制,虽然它功能很强大,但是实现起来却并不是很难,从表象上来理解:当代码在执行过程中,遭遇到 return 和 goto 等类似的语句所引发作用域(代码执行流)转移时,便会产生一个局部展开( Local Unwinding );而由于异常而导致的 finally 块被执行的过程,往往被称为全局展开( Global Unwinding )。由于展开( Unwinding )而导致的 finally 块被执行的过程,非常类似于一个子函数(或子过程)被调用的过程。例如,当在 try 块中最后一条语句 return 被执行到的时候,一个展开操作便发生了,可以把展开操作想象成,是编译器在 return 语句之前插入了一些代码(这些代码完成对 finally 块的调用),因此可以得出结论: finally 区域内的代码块,肯定是在 return 之前被执行。
但是,请特别注意, finally 块区域中的代码虽然在 return 语句之前被执行,但是 finally 块区域中的代码是不能够通过重新赋值的方式来改变 return 语句的返回值。请看如下的示例代码:
public class FinallyTest {
public static void main(String[] args){
// 你认为 test 函数返回的值是多少呢?
System.out.println("test 的返回值为: " + test());
}
public static int test(){
int ret = 1;
try{
System.out.println("in try block");
return (ret);
}catch (Exception e){
System.out.println("in catch block");
e.printStackTrace();
}finally{
// 注意,这里重新改变了 ret 的值。
ret = 2;
System.out.println("in finally block!");
}
return ret;
}
}
输出如下:
in try block
in finally block!
test 的返回值为: 1
上面刚刚说了, finally 块区域中的代码不会轻易影响 try 区域中 return 语句的返回值,但是有一种情况例外,那就是在 finally 内部使用 return 语句。示例程序如下:
public class FinallyTest {
public static void main(String[] args){
// 你认为 test 函数返回的值是多少呢?
System.out.println("test 的返回值为: " + test());
}
@SuppressWarnings("finally")
public static int test(){
int ret = 1;
try{
System.out.println("in try block");
return (ret);
}catch (Exception e){
System.out.println("in catch block");
e.printStackTrace();
}finally{
// 注意,这里重新改变了 ret 的值。
ret = 2;
System.out.println("in finally block!");
return ret;
}
}
}
输出如下:
in try block
in finally block!
test 的返回值为: 2
也许大多数朋友都估计到,上面的 test 函数返回值是 2 。也即是说, finally 内部使用 return 语句后,它影响(覆盖了) try 区域中 return 语句的返回值。这真是一种特别糟糕的情况,虽然它表面上看起来不是那么严重,但是这种程序极易给它人造成误解(使得阅读该代码的人总得担心或考虑,是否有其它地方影响了这里的 return 的返回值)。
之所以出现这种现象的真正原因是,由于 finally 区域中的代码先于 return 语句( try 作用域中的)被执行,但是,如果此时在 finally 内部也有一个 return 语句,这将会导致该函数直接就返回了,而致使 try 作用域中的 return 语句再也得不到执行机会(实际就是无效代码,被覆盖了)。
面对上述情况,其实更合理的做法是,既不在 try block 内部中使用 return 语句,也不在 finally 内部使用 return 语句,而应该在 finally 语句之后使用 return 来表示函数的结束和返回,把上面的程序改造一下,代码如下 :
public class FinallyTest {
public static void main(String[] args){
// 你认为 test 函数返回的值是多少呢?
System.out.println("test 的返回值为: " + test());
}
@SuppressWarnings("finally")
public static int test(){
int ret = 1;
try{
System.out.println("in try block");
}catch (Exception e){
System.out.println("in catch block");
e.printStackTrace();
}finally{
// 注意,这里重新改变了 ret 的值。
ret = 2;
System.out.println("in finally block!");
}
return ret;
}
}
输出如下:
in try block
in finally block!
test 的返回值为: 2
Java提供了两类主要的 异常:runtime exception和checked exception。所有的checked exception是从java.lang.Exception类衍生出来的,而runtime exception则是从java.lang.RuntimeException或java.lang.Error类衍生出来的。
它们的不同之处表现在两方面:机制上和逻辑上。
一、机制上
它们在机制上的不同表现在两点:1.如何定义方法;2. 如何处理抛出的异常。请看下面CheckedException的定义:
以下是引用片段:
public class CheckedException extends Exception
{
public CheckedException() {}
public CheckedException( String message )
{
super( message );
}
}
以及一个使用exception的例子:
以下是引用片段:
public class ExceptionalClass
{
public void method1()
throws CheckedException
{
// ... throw new CheckedException( “...出错了“ );
}
public void method2( String arg )
{
if( arg == null )
{
throw new NullPointerException( “method2的参数arg是null!” );
}
}
public void method3() throws CheckedException
{
method1();
}
}
你可能已经注意到了,两个方法method1()和method2()都会抛出exception,可是只有method1()做了声明。另外, method3()本身并不会抛出exception,可是它却声明会抛出CheckedException。在向你解释之前,让我们先来看看这个类的 main()方法:
以下是引用片段:
public static void main( String[] args )
{
ExceptionalClass example = new ExceptionalClass();
try
{
example.method1();
example.method3();
}
catch( CheckedException ex ) { } example.method2( null );
}
在main()方法中,如果要调用method1(),你必须把这个调用放在try/catch程序块当中,因为它会抛出Checked exception。
相比之下,当你调用method2()时,则不需要把它放在try/catch程序块当中,因为它会抛出的exception不是checked exception,而是runtime exception。会抛出runtime exception的方法在定义时不必声明它会抛出exception。
现在,让我们再来看看method3()。它调用了 method1()却没有把这个调用放在try/catch程序块当中。它是通过声明它会抛出method1()会抛出的exception来避免这样做 的。它没有捕获这个exception,而是把它传递下去。实际上main()方法也可以这样做,通过声明它会抛出Checked exception来避免使用try/catch程序块(当然我们反对这种做法)。
小结一下:
* Runtime exceptions:
在定义方法时不需要声明会抛出runtime exception;
在调用这个方法时不需要捕获这个runtime exception;
runtime exception是从java.lang.RuntimeException或java.lang.Error类衍生出来的。
* Checked exceptions:
定义方法时必须声明所有可能会抛出的checked exception;
在调用这个方法时,必须捕获它的checked exception,不然就得把它的exception传递下去;
checked exception是从java.lang.Exception类衍生出来的。
二、逻辑上
从逻辑的角度来说,checked exceptions和runtime exception是有不同的使用目的的。checked exception用来指示一种调用方能够直接处理的异常情况。而runtime exception则用来指示一种调用方本身无法处理或恢复的程序错误。
分享到:
相关推荐
14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理机制.zip14.java异常处理...
深入理解java异常处理机制,很详细的,去了,你们的!
异常处理是Java语言的重要机制,正确、合理地处理异常对系统的健壮性和稳定性提供了强有力的支持。异常的处理主要包括捕捉异常、程序流程的跳转和异常处理语句块的定义等。
异常处理机制是面向对象语言普遍支持的提高软件可靠性的方法。作为两款被广泛使用的面向对象语言,C++和Java语言都支持异常处理机制...该算法可以同时支持C++和Java异常处理机制,并有效提高了抛出异常较多的程序的性能。
主要介绍了java异常处理机制示例(java抛出异常、捕获、断言),需要的朋友可以参考下
深入理解java异常处理机制Java开发Java经验技巧共19页.pdf.zip
java异常处理机制主要依赖于try,catch,finally,throw,throws五个关键字。 try 关键字后紧跟一个花括号括起来的代码块,简称try块。同理:下面的也被称为相应的块。 它里面可置引发异常的代码。catch后...
基于Java异常处理机制的研究,张军芳,肖华山,异常处理是Java语言的重要机制,有效地处理异常对程序的可靠性、健壮性是十分重要的。本文分析了异常处理机制的概念和指导原则,��
上海交通大学 Java语言程序设计 JAVA讲义 第08章 java异常处理机制(共45页).ppt 上海交通大学 Java语言程序设计 JAVA讲义 第09章 Java输入输出及文件操作(共82页).ppt 上海交通大学 Java语言程序设计 JAVA讲义 ...
浅析Java异常处理机制.pdf
Java异常处理机制应用研究
Java异常处理机制及应用
【完整课程列表】 ...09 Java异常处理机制和调试(共32页).ppt 10 java集合框架(共27页).ppt 11 JAVA UI swing编程基础(共39页).ppt 12 AWT布局管理器(共14页).ppt 13 AWT事件处理模型(共29页).ppt
基于Java异常处理机制的软件健壮性研究最终版.pdf
Java异常处理机制及应用研究
基于Java异常处理机制的分析.pdf