覆盖一个方法时,只能产生已在方法的基础类版本中定义的异常,或者是基类版本中定义的异常的子类。
但是可以在基类声明抛出异常时,覆盖的子类不抛出异常。
这意味着与基类协同工作的代码也会自动应用于衍生类。
可以声明一场却不抛出异常,因为可能在子类中抛出这些异常。
构建器不受上述影响。
除了将内存设置为默认状态外,如果还需要设置一些其他值,finally就是必须的。
如果调用了continue和break,finally机制还是能够工作。
丢失异常:
public class LostMessage {
void f() throws VeryImportantException {
throw new VeryImportantException();
}
void dispose() throws TrivalException {
throw new TrivalException();
}
public static void main(String[] args) throws VeryImportantException, TrivalException {
LostMessage lostMessage = new LostMessage();
try {
lostMessage.f();
} finally {
lostMessage.dispose();
}
}
}
class VeryImportantException extends Exception {
@Override
public String toString() {
return "Very Important";
}
}
class TrivalException extends Exception {
@Override
public String toString() {
return "Trival";
}
}
在此例中,不存在VeryImportantException(非常重要的违例)的迹象,它只是简单地被finally从句中的TrivalException 代替了。
构建器:
class InputFile {
private BufferedReader in;
InputFile(String fname) throws Exception {
try {
in = new BufferedReader(new FileReader(fname));
// Other code that might throw exceptions
} catch (FileNotFoundException e) {
System.err.println("Could not open " + fname);
// Wasn't open, so don't close it
throw e;
} catch (Exception e) {
// All other exceptions must close it
try {
in.close();
} catch (IOException e2) {
System.err.println("in.close() unsuccessful");
}
throw e;
} finally {
// Don't close it here!!!
}
}
String getLine() {
String s;
try {
s = in.readLine();
} catch (IOException e) {
System.err.println("readLine() unsuccessful");
s = "failed";
}
return s;
}
void cleanup() {
try {
in.close();
} catch (IOException e2) {
System.err.println("in.close() unsuccessful");
}
}
}
public class Cleanup {
public static void main(String[] args) {
try {
InputFile in = new InputFile("Cleanup.java");
String s;
int i = 1;
while ((s = in.getLine()) != null)
System.out.println("" + i++ + ": " + s);
in.cleanup();
} catch (Exception e) {
System.err.println("Caught in main, e.printStackTrace()");
e.printStackTrace();
}
}
}
若FileReader构建器不成功,就会产生一个FileNotFoundException(文件未找到违例)。必须单独捕获这个违例——这属于我们不想关闭文件的一种特殊情况,因为文件尚未成功打开。
执行完本地操作后,违例会被重新“掷”出。这样做是必要的,因为这个构建器的执行已经失败,我们不希望调用方法来假设对象已正确创建以及有效。
Java的一项缺陷——除内存清除之外的所有清除都不会自动进行,所以必须知会客户程序员,告诉他们有责任用finalize()保证清除工作的正确进行。
catch(Annoyance e)能捕获一个Annoyance以及从它衍生的任何类。
这一点非常重要,因为一旦我们决定为一个方法添加更多的违例,而且它们都是从相同的基础类继承的,那么客户程序员的代码就不需要更改。至少能够假定它们捕获的是基础类。
若将基础类捕获从句置于第一位,试图“屏蔽”衍生类违例,则编译器会产生一条出错消息,因为它发现永远不可能抵达Sneeze捕获从句。
其中最大的挑战似乎是如何覆盖所有可能的因素。不仅有三种不同的种类的IO需要考虑(文件、控制台、网络连接),而且需要通过大量不同的方式与它们通信(顺序、随机访问、二进制、字符、按行、按字等等)。