Java Exception学习总结

众所周知,在Java中捕获违例的方法:

try{ 

 }catch(Exception e){

 e.printStack();

 }

1、违例的作用:

在违例控制理论中,共存在两种基本方法。在“中断”方法中(Java 和 C++提供了对这种方法的支持),我
们假定错误非常关键,没有办法返回违例发生的地方。无论谁只要“掷”出一个违例,就表明没有办法补救
错误,而且也不希望再回来。
另一种方法叫作“恢复”。它意味着违例控制器有责任来纠正当前的状况,然后取得出错的方法,假定下一
次会成功执行。若使用恢复,意味着在违例得到控制以后仍然想继续执行。在这种情况下,我们的违例更象
一个方法调用——我们用它在Java 中设置各种各样特殊的环境,产生类似于“恢复”的行为(换言之,此时
不是“掷”出一个违例,而是调用一个用于解决问题的方法)。另外,也可以将自己的try块置入一个
while 循环里,用它不断进入try 块,直到结果满意时为止。
从历史的角度看,若程序员使用的操作系统支持可恢复的违例控制,最终都会用到类似于中断的代码,并跳
过恢复进程。所以尽管“恢复”表面上十分不错,但在实际应用中却显得困难重重。其中决定性的原因可能
是:我们的控制模块必须随时留意是否产生了违例,以及是否包含了由产生位置专用的代码。这便使代码很

难编写和维护——大型系统尤其如此,因为违例可能在多个位置产生。

2、标准 Java 违例
Java 包含了一个名为Throwable 的类,它对可以作为违例“掷”出的所有东西进行了描述。Throwable 对象
有两种常规类型(亦即“从Throwable 继承”)。其中,Error 代表编译期和系统错误,我们一般不必特意
捕获它们(除在特殊情况以外)。Exception 是可以从任何标准Java 库的类方法中“掷”出的基本类型。此
外,它们亦可从我们自己的方法以及运行期偶发事件中“掷”出。
为获得违例的一个综合概念,最好的方法是阅读由 http://java.sun.com提供的联机 Java 文档(当然,首先
下载它们更好)。为了对各种违例有一个大概的印象,这个工作是相当有价值的。但大家不久就会发现,除
名字外,一个违例和下一个违例之间并不存在任何特殊的地方。此外,Java 提供的违例数量正在日益增多;
从本质上说,把它们印到一本书里是没有意义的。大家从其他地方获得的任何新库可能也提供了它们自己的
违例。我们最需要掌握的是基本概念,以及用这些违例能够做什么。
java.lang.Exception
这是程序能捕获的基本违例。其他违例都是从它衍生出去的。这里要注意的是违例的名字代表发生的问题,
而且违例名通常都是精心挑选的,可以很清楚地说明到底发生了什么事情。违例并不全是在java.lang 中定
义的;有些是为了提供对其他库的支持,如util,net以及io等——我们可以从它们的完整类名中看出这一

点,或者观察它们从什么继承。例如,所有IO违例都是从 java.io.IOException 继承的。

3、创建自己的违例
并不一定非要使用Java 违例。这一点必须掌握,因为经常都需要创建自己的违例,以便指出自己的库可能生
成的一个特殊错误——但创建Java 分级结构的时候,这个错误是无法预知的。
为创建自己的违例类,必须从一个现有的违例类型继承——最好在含义上与新违例近似。继承一个违例相当
简单:
//: Inheriting.java
// Inheriting your own exceptions
class MyException extends Exception {
public MyException() {}
public MyException(String msg) {
super(msg);
}
}
public class Inheriting {
public static void f() throws MyException {
System.out.println(
"Throwing MyException from f()");
throw new MyException();
}
public static void g() throws MyException {
System.out.println(
"Throwing MyException from g()");
throw new MyException("Originated in g()");
}
public static void main(String[] args) {
try {
 272
f();
} catch(MyException e) {
e.printStackTrace();
}
try {
g();
} catch(MyException e) {
e.printStackTrace();
}
}
} ///:~
继承在创建新类时发生:
class MyException extends Exception {
public MyException() {}
public MyException(String msg) {
super(msg);
}
}
这里的关键是“extends Exception”,它的意思是:除包括一个 Exception 的全部含义以外,还有更多的含
义。增加的代码数量非常少——实际只添加了两个构建器,对 MyException的创建方式进行了定义。请记
住,假如我们不明确调用一个基础类构建器,编译器会自动调用基础类默认构建器。在第二个构建器中,通
过使用super 关键字,明确调用了带有一个 String参数的基础类构建器。
该程序输出结果如下:
Throwing MyException from f()
MyException
at Inheriting.f(Inheriting.java:16)
at Inheriting.main(Inheriting.java:24)
Throwing MyException from g()
MyException: Originated in g()
at Inheriting.g(Inheriting.java:20)
at Inheriting.main(Inheriting.java:29)
可以看到,在从f()“掷”出的 MyException 违例中,缺乏详细的消息。
创建自己的违例时,还可以采取更多的操作。我们可添加额外的构建器及成员:
//: Inheriting2.java
// Inheriting your own exceptions
class MyException2 extends Exception {
public MyException2() {}
public MyException2(String msg) {
super(msg);
}
public MyException2(String msg, int x) {
super(msg);
i = x;
}
public int val() { return i; }
 273
private int i;
}
public class Inheriting2 {
public static void f() throws MyException2 {
System.out.println(
"Throwing MyException2 from f()");
throw new MyException2();
}
public static void g() throws MyException2 {
System.out.println(
"Throwing MyException2 from g()");
throw new MyException2("Originated in g()");
}
public static void h() throws MyException2 {
System.out.println(
"Throwing MyException2 from h()");
throw new MyException2(
"Originated in h()", 47);
}
public static void main(String[] args) {
try {
f();
} catch(MyException2 e) {
e.printStackTrace();
}
try {
g();
} catch(MyException2 e) {
e.printStackTrace();
}
try {
h();
} catch(MyException2 e) {
e.printStackTrace();
System.out.println("e.val() = " + e.val());
}
}
} ///:~
此时添加了一个数据成员i;同时添加了一个特殊的方法,用它读取那个值;也添加了一个额外的构建器,
用它设置那个值。输出结果如下:
Throwing MyException2 from f()
MyException2
at Inheriting2.f(Inheriting2.java:22)
at Inheriting2.main(Inheriting2.java:34)
Throwing MyException2 from g()
MyException2: Originated in g()
at Inheriting2.g(Inheriting2.java:26)
at Inheriting2.main(Inheriting2.java:39)
Throwing MyException2 from h()
 274
MyException2: Originated in h()
at Inheriting2.h(Inheriting2.java:30)
at Inheriting2.main(Inheriting2.java:44)
e.val() = 47
由于违例不过是另一种形式的对象,所以可以继续这个进程,进一步增强违例类的能力。但要注意,对使用
自己这个包的客户程序员来说,他们可能错过所有这些增强。因为他们可能只是简单地寻找准备生成的违
例,除此以外不做任何事情——这是大多数 Java 库违例的标准用法。若出现这种情况,有可能创建一个新违
例类型,其中几乎不包含任何代码:
//: SimpleException.java
class SimpleException extends Exception {
} ///:~
它要依赖编译器来创建默认构建器(会自动调用基础类的默认构建器)。当然,在这种情况下,我们不会得

到一个SimpleException(String)构建器,但它实际上也不会经常用到。

4、违例匹配
“掷”出一个违例后,违例控制系统会按当初编写的顺序搜索“最接近”的控制器。一旦找到相符的控制
器,就认为违例已得到控制,不再进行更多的搜索工作。
在违例和它的控制器之间,并不需要非常精确的匹配。一个衍生类对象可与基础类的一个控制器相配,如下
例所示:
//: Human.java
// Catching Exception Hierarchies
class Annoyance extends Exception {}
class Sneeze extends Annoyance {}
public class Human {
public static void main(String[] args) {
try {
throw new Sneeze();
} catch(Sneeze s) {
System.out.println("Caught Sneeze");
} catch(Annoyance a) {
System.out.println("Caught Annoyance");
}
}
} ///:~
Sneeze违例会被相符的第一个 catch 从句捕获。当然,这只是第一个。然而,假如我们删除第一个 catch从
句:
try {
throw new Sneeze();
} catch(Annoyance a) {
System.out.println("Caught Annoyance");
}
那么剩下的 catch从句依然能够工作,因为它捕获的是 Sneeze的基础类。换言之,catch(Annoyance e)能捕
获一个Annoyance 以及从它衍生的任何类。这一点非常重要,因为一旦我们决定为一个方法添加更多的违
例,而且它们都是从相同的基础类继承的,那么客户程序员的代码就不需要更改。至少能够假定它们捕获的
是基础类。
若将基础类捕获从句置于第一位,试图“屏蔽”衍生类违例,就象下面这样:
try {
throw new Sneeze();
} catch(Annoyance a) {
System.out.println("Caught Annoyance");
} catch(Sneeze s) {
System.out.println("Caught Sneeze");
 284
}
则编译器会产生一条出错消息,因为它发现永远不可能抵达Sneeze 捕获从句。
5 违例准则
用违例做下面这些事情:
(1) 解决问题并再次调用造成违例的方法。
(2) 平息事态的发展,并在不重新尝试方法的前提下继续。
(3) 计算另一些结果,而不是希望方法产生的结果。
(4) 在当前环境中尽可能解决问题,以及将相同的违例重新“掷”出一个更高级的环境。
(5) 在当前环境中尽可能解决问题,以及将不同的违例重新“掷”出一个更高级的环境。
(6) 中止程序执行。
(7) 简化编码。若违例方案使事情变得更加复杂,那就会令人非常烦恼,不如不用。
(8) 使自己的库和程序变得更加安全。这既是一种“短期投资”(便于调试),也是一种“长期投资”(改
善应用程序的健壮性)
6 总结
通过先进的错误纠正与恢复机制,我们可以有效地增强代码的健壮程度。对我们编写的每个程序来说,错误
恢复都属于一个基本的考虑目标。它在Java 中显得尤为重要,因为该语言的一个目标就是创建不同的程序组
件,以便其他用户(客户程序员)使用。为构建一套健壮的系统,每个组件都必须非常健壮。
在Java 里,违例控制的目的是使用尽可能精简的代码创建大型、可靠的应用程序,同时排除程序里那些不能
控制的错误。
违例的概念很难掌握。但只有很好地运用它,才可使自己的项目立即获得显著的收益。Java 强迫遵守违例所
有方面的问题,所以无论库设计者还是客户程序员,都能够连续一致地使用它。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33275597/article/details/79950925
文章标签: java异常
个人分类: java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭