并不一定非要使用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 {
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; }
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()
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)构建器,但它实际上也不会经常用到。
闽公网安备 35060202000074号