彻底明白JAVA的异常处理-2

原创 2003年11月23日 19:17:00

2.         异常规格(exception specification

1)        在函数定义时可以声明异常规格。如果一个函数在异常规格中声明了non-RuntimeException异常,那么当调用这个函数时,就一定要捕捉异常规格中的non-RuntimeException异常。

import java.lang.RuntimeException;

import java.lang.NullPointerException;

import java.sql.SQLException;

class TestException{

       //1)异常规格中声明将抛出RuntimeException异常<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

public void testRuntime() throws RuntimeException {}

//2)异常规格中声明将抛出NullPointerException异常

public void testNullPointer() throws NullPointerException {}

//3)异常规格中声明将抛出non-RuntimeException异常

    public void testNonRuntime() throws SQLException {}

}

public class Test{  

    public static void main(String[] args){

        TestException te = new TestException();

        te.testRuntime(); //4

        te.testNullPointer(); //5

        //te.testNonRuntime(); 6

        try{

            te.testNonRuntime();

        }

        catch(SQLException ex){}

    }

}

在上述代码中,(1)处在异常规格中声明将抛出RuntimeException;(2)在异常规格中声明将抛出NullPointerException,而NullPointerExceptionRuntimeException的子类,所以在调用这两个函数时,可不捕捉异常,如(4)(5)处的代码一样直接调用。但(3)处在异常规格中声明将抛出SQLException,而SQLException不是RuntimeException的子类,所以必须捕捉SQLException异常。

2)        如果要在一个函数中抛出non-RuntimeException异常,则必须要在异常规格中声明该异常。

import java.sql.SQLException;

import java.io.IOException;

class Test1{

    public void f() throws SQLException{ //2

       throw new IOException("IOException");  //1

    }

}

public class ExplicitStatic{  

    public static void main(String[] args){

        Test1 te = new Test1();

        try{

            te.f();

        }

        catch(Exception ex){

            System.out.println("catch Exception in main");

        }

    }

}

在(1)处抛出了一个没有在异常规格中被声明的non-RuntimeException异常,在编译时会出错。

2.         取得异常中的信息的几个函数

1)        String getMessage()getLocalizedMessage toString

取得异常对象中的信息

              import java.lang.RuntimeException;

import java.lang.NullPointerException;

Import java.sql.SQLException;

import java.io.IOException;

class TestException{

                  public void tSql() throws SQLException {

                      System.out.println("Originating the exception in tSql()");

                      throw new SQLException("throw in tSql");

                  }

}

public class Test{  

                  public static void main(String[] args){

                      TestException te = new TestException();

                      try{

                          te.tSql();

                      }

                      catch(SQLException ex){

                          System.out.println("catch SQLException in main");

                          System.out.println("ex.getMessage()" + ex.getMessage());

System.out.println("ex.getLocalizedMessage()" +

ex.getLocalizedMessage());

                          System.out.println("ex.toString()" + ex.toString());

                      }

                      catch(Exception ex){

                          System.out.println("catch Exception in main");

                      }

                  }

}

       运行结果:

       Originating the exception in tSql()

catch SQLException in main

ex.getMessage()throw in tSql

ex.getLocalizedMessage()throw in tSql

ex.toString()java.sql.SQLException: throw in tSql

2)        void printStackTrace()Throwable fillStackTrace()

printStackTrace打印出Throwable和其call stack trace

FillStackTrace则在调用点设立新的stack trace信息

import java.sql.SQLException;

class TestException{

    public static void tSql() throws SQLException {

        System.out.println("Originating the exception in tSql()");

        throw new SQLException("throw in tSql");

    }

    public void f() throws SQLException{

        try{

            tSql();

        }

        catch(SQLException ex){

            System.out.println("In f(), e.printStackTrace()");

            ex.printStackTrace();

throw ex; //1

//throw (SQLException)ex.fillInStackTrace(); 2

        }

    }

}

public class Test{  

    public static void main(String[] args){

        TestException te = new TestException();

        try{

            te.f();

        }

        catch(SQLException ex){

            System.out.println("catch in main, e.printStackTrace()");

            ex.printStackTrace();

        }

        catch(Exception ex){

            System.out.println("catch Exception in main");

        }

    }

}

结果为:

Originating the exception in tSql()

In f(), e.printStackTrace()

catch in main, e.printStackTrace()

java.sql.SQLException: throw in tSql

       void TestException.tSql()

              Test.java:5

       void TestException.f()

              Test.java:9

       void Test.main(java.lang.String[])

              Test.java:22

java.sql.SQLException: throw in tSql

       void TestException.tSql()

              Test.java:5

       void TestException.f()

              Test.java:9

       void Test.main(java.lang.String[])

              Test.java:22

                     如果把(1)处代码注释掉,并去年(2)处代码的注释,结果将变成:

Originating the exception in tSql()

In f(), e.printStackTrace()

catch in main, e.printStackTrace()

java.sql.SQLException: throw in tSql

       void TestException.tSql() //3

              Test.java:6

       void TestException.f()

              Test.java:10

       void Test.main(java.lang.String[])

              Test.java:24

java.sql.SQLException: throw in tSql

       void TestException.f() //4

              Test.java:16

       void Test.main(java.lang.String[])

              Test.java:24

由于在代码(2)处设立新的stack trace信息,所以异常会被认为是在f()中发出的,所以在main()中得到的异常原始抛出点为f()(见(3)),而在f()中为tSql()(见(6))。

3)        如果重新抛出一个不同类型的异常,也能产生fillStackTrace()函数的效果。如果把上面代码的f()函数修改成下面的样子:

public void f() throws SQLException,IOException{

try{

        tSql();

    }

    catch(SQLException ex){

        System.out.println("In f(), e.printStackTrace()");

        ex.printStackTrace();      

        throw new IOException(); //1

    }

}

则结果为:

Originating the exception in tSql()

In f(), e.printStackTrace()

catch Exception in main

java.sql.SQLException: throw in tSql

       void TestException.tSql()

              Test.java:6

       void TestException.f()

              Test.java:10

       void Test.main(java.lang.String[])

              Test.java:25

java.io.IOException

       void TestException.f()

              Test.java:17

       void Test.main(java.lang.String[])

              Test.java:25

由于在(1)处抛出了一个新的类型的异常,那么在main()中捕捉到的是新的异常,所以在main()中捕捉到的异常的原始抛出点为f()

3.         RuntimeException异常

RuntimeException及其子类所代表的异常我们在程序中不用进行捕捉,如果发生此类异常,Java会自动抛出相应的异常对象,如:

class TestException{   

    public static void g(int x) {

        System.out.println("10/" + x + " = " + 10/x);

    }

}

public class Test{  

    public static void main(String[] args){

        TestException.g(2);

        TestException.g(0); //1

    }

}

上面代码在编译时不会发生错误,只有在运行时(1)处会发生错误。虽然除法可能会存在错误,但我们不用进行捕捉,当发生错误时,Java会自动抛出相应异常。

二.finally进行清理

1.         如果某段代码不管是否发生异常都要执行,那可把它改入finally块中。

import java.sql.SQLException;

class TestException{

    public static void tSql() throws SQLException {

        System.out.println("Originating the exception in tSql()");

        throw new SQLException("throw in tSql");

    }

    public void f() throws SQLException{

        try{

            tSql();

        }

        catch(SQLException ex){

            System.out.println("catch SQLException in f()");

            throw ex; //1

        } 

        finally{

            System.out.println("finally in f()");

        }

    }

}

public class Test{  

    public static void main(String[] args){

        TestException te = new TestException();

        try{

            te.f();

        }

        catch(SQLException ex){

            System.out.println("catch te.f() SQLException in main");

        }

        catch(Exception ex){

            System.out.println("catch te.f() Exception in main");

        }

    }

}

运行结果为:

Originating the exception in tSql()

catch SQLException in f()

finally in f()

catch te.f() SQLException in main

虽然在代码(1)处重新抛出异常,但finally块中的代码仍然会被执行。

2.         finally造成的异常遗失

如果在finally中执行的代码又产生异常,那么在上一层调用中所捕捉到的异常的起始抛出点会是finally所在的函数。

import java.sql.SQLException;

class TestException{

    public static void tSql1() throws SQLException {

        System.out.println("Originating the exception in tSql()");

        throw new SQLException("throw in tSql1");

    }

    public static void tSql2() throws SQLException {

        System.out.println("Originating the exception in tSql()");

        throw new SQLException("throw in tSql2");

    }

    public void f() throws SQLException{

        try{

            tSql1();

        }

        catch(SQLException ex){

            System.out.println("catch SQLException in f()");

            throw ex; //2

        } 

        finally{

            System.out.println("finally in f()");

            //tSql2(); (1

        }

    }

}

public class Test{  

    public static void main(String[] args){

        TestException te = new TestException();

        try{

            te.f();

        }

        catch(SQLException ex){

            System.out.println("catch te.f() SQLException in main");

            System.out.println("getMessage" + ex.getMessage());

            System.out.println("printStackTrace");

            ex.printStackTrace();

        }

    }

}

运行结果为:

Originating the exception in tSql()

catch SQLException in f()

finally in f()

catch te.f() SQLException in main

getMessagethrow in tSql1

printStackTrace

java.sql.SQLException: throw in tSql1

       void TestException.tSql1()

              Test.java:5

       void TestException.f()

              Test.java:13

       void Test.main(java.lang.String[])

              Test.java:29

从结果可以看出,在main()中能正确打印出所捕捉到的异常的起始抛出点。但如果去掉代码(1)的注释,结果将变为:

Originating the exception in tSql()

catch SQLException in f()

finally in f()

Originating the exception in tSql()

catch te.f() SQLException in main

getMessagethrow in tSql2

printStackTrace

java.sql.SQLException: throw in tSql2

       void TestException.tSql2()

              Test.java:9

       void TestException.f()

              Test.java:21

       void Test.main(java.lang.String[])

              Test.java:29

从结果可以看出,在main()中捕捉到的异常是finally中产生的异常,代码(2)中抛出的异常丢失了。

彻底明白JAVA的异常处理-1

一.基本异常1.         抛出异常的原理1)        像产生一个Java对象那样在heap上以new产生一个异常对象。2)        停止目前的执行路线,将上述那个异常对象的refe...
  • Nepalon
  • Nepalon
  • 2003年11月23日 19:18
  • 1422

彻底明白JAVA的异常处理 -3

四.继承中异常1.         关于构造函数中的异常1.1          构造函数中的异常规则某个derived class构造函数的“异常规格接口“可以比其所调用的父类的构造函数的异常规格接...
  • Nepalon
  • Nepalon
  • 2003年11月23日 19:17
  • 1255

彻底明白红黑树(2)

引言:  昨天下午画红黑树画了好几个钟头,总共10页纸。 特此,再深入剖析红黑树的算法实现,教你如何彻底实现红黑树算法。 经过我上一篇博文,“教你透彻了解红黑树”后,相信大家对红黑树已经有了一定...
  • andamajing
  • andamajing
  • 2012年10月17日 15:46
  • 1265

彻底明白Java的IO系统-2

一.Input和Output1.         stream代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源。在Java的IO中,所有的stream(包括Input和Out str...
  • Nepalon
  • Nepalon
  • 2003年12月13日 02:23
  • 1297

java值传递彻底明白~

时间: 2004-4-06 13:18:27    标题: 一个绝对害了不少人的Java技术问题! 我不记得自己是怎么学到的,但是我相信绝大部分从事java学习Java的人都一直这么以为一个小的技术问...
  • faintbear
  • faintbear
  • 2004年11月29日 16:24
  • 13921

彻底明白Java的多线程

彻底明白Java的多线程-线程间的通信(1) 作者:恒善喜 来源:不详 (2006-06-02 14:51:45)   线程间的通信1. 线程的几种状态线程有四种状态,任何一个线程肯定处于这四种状态中...
  • hehuii
  • hehuii
  • 2008年04月07日 10:38
  • 1337

彻底明白IP地址(2)

彻底明白IP地址(1) IP地址的介绍 1、IP地址的表示方法IP地址 = 网络号+主机号    把整个Internet网堪称单一的网络,IP地址就是给每个连在Internet网的主机分配一个在全世界...
  • Hugohut
  • Hugohut
  • 2010年05月22日 00:24
  • 566

彻底明白Android中AIDL及其使用

对于AIDL不少人的理解是,AIDL可以完成应用之间的通讯,那么Android推出Messager不就是完成应用之间通讯的嘛,那么AIDL和Messager有什么不同。多点时间研究一下,分享一下我的结...
  • wangduanqing5945
  • wangduanqing5945
  • 2014年06月27日 11:36
  • 1291

彻底掌握JAVA的异常处理

异常:阻止当前方法或作用域继续执行的问题。特别需要注意的,程序抛出异常,不管这个异常是否严重,都必须进行处理,决不能有运算结果不出错就是正常的想法。 先来看看异常有哪些类: Throwable类是...
  • springcsc1982
  • springcsc1982
  • 2013年04月17日 16:14
  • 909

彻底搞明白java synchronized

本文来着点击打开链接     http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html 1、synchronized关键...
  • zgliang88
  • zgliang88
  • 2014年01月14日 21:07
  • 345
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:彻底明白JAVA的异常处理-2
举报原因:
原因补充:

(最多只允许输入30个字)