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