分享
 
 
 

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

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

2. 异常规格(exceptionspecification)

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

import java.lang.RuntimeException;

import java.lang.NullPointerException;

import java.sql.SQLException;

class TestException{

//(1)异常规格中声明将抛出RuntimeException异常

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,而NullPointerException是RuntimeException的子类,所以在调用这两个函数时,可不捕捉异常,如(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和其callstacktrace。

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

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)处设立新的stacktrace信息,所以异常会被认为是在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

getMessage:throw 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

getMessage:throw 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)中抛出的异常丢失了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有