29.JAVA编程思想——构建器
来源:互联网 发布:美国大非农数据预测 编辑:程序博客网 时间:2024/05/22 06:02
29.JAVA编程思想——构建器
为违例编写代码时,我们经常要解决的一个问题是:“一旦产生违例,会正确地进行清除吗?”大多数时候都会非常安全,但在构建器中却是一个大问题。构建器将对象置于一个安全的起始状态,但它可能执行一些操作——如打开一个文件。除非用户完成对象的使用,并调用一个特殊的清除方法,否则那些操作不会得到正确的清除。若从一个构建器内部“掷”出一个违例,这些清除行为也可能不会正确地发生。所有这些都意味着在编写构建器时,我们必须特别加以留意。
由于前面刚学了finally,所以大家可能认为它是一种合适的方案。但事情并没有这么简单,因为finally每次都会执行清除代码——即使我们在清除方法运行之前不想执行清除代码。因此,假如真的用finally 进行清除,必须在构建器正常结束时设置某种形式的标志。而且只要设置了标志,就不要执行finally 块内的任何东西。由于这种做法并不完美(需要将一个地方的代码同另一个地方的结合起来),所以除非特别需要,否则一般不要尝试在finally 中进行这种形式的清除。
在下面这个例子里,创建了一个名为InputFile 的类。它的作用是打开一个文件,然后每次读取它的一行内容(转换为一个字串)。它利用了由Java 标准IO 库提供的FileReader以及BufferedReader 类(将于。这两个类都非常简单,现在可以毫无困难地掌握它们的基本用法:
1 代码
import java.io.*;
class InputFile {
private BufferedReaderin;
InputFile(String fname) throws Exception {
try {
in =new BufferedReader(new FileReader(fname));
// Other code that might throw exceptions
} catch (FileNotFoundExceptione) {
System.out.println("Could not open "+fname);
// Wasn't open, so don't close it
throwe;
} catch (Exceptione) {
// All other exceptions must close it
try {
in.close();
} catch (IOExceptione2) {
System.out.println("in.close() unsuccessful");
}
throwe;
} finally {
// Don't close it here!!!
}
}
String getLine() {
String s;
try {
s =in.readLine();
} catch (IOExceptione) {
System.out.println("readLine() unsuccessful");
s ="failed";
}
returns;
}
void cleanup() {
try {
in.close();
} catch (IOExceptione2) {
System.out.println("in.close() unsuccessful");
}
}
}
publicclass Cleanup {
publicstaticvoidmain(String[]args){
try {
InputFile in = new InputFile("Cleanup.java");
String s;
inti = 1;
while ((s =in.getLine()) != null)
System.out.println("" +i++ + ": " +s);
in.cleanup();
} catch (Exceptione) {
System.out.println("Caught in main, e.printStackTrace()");
e.printStackTrace();
}
}
} /// :~
2 说明
Couldnot open Cleanup.java
Caughtin main, e.printStackTrace()
java.io.FileNotFoundException:Cleanup.java (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(UnknownSource)
atjava.io.FileInputStream.<init>(Unknown Source)
atjava.io.FileInputStream.<init>(Unknown Source)
at java.io.FileReader.<init>(UnknownSource)
at InputFile.<init>(Cleanup.java:8)
at Cleanup.main(Cleanup.java:50)
用于InputFile 的构建器采用了一个String(字串)参数,它代表我们想打开的那个文件的名字。在一个try 块内部,它用该文件名创建了一个FileReader。对FileReader 来说,除非转移并用它创建一个能够实际与之“交谈”的BufferedReader,否则便没什么用处。注意InputFile 的一个好处就是它同时合并了这两种行动。
若FileReader 构建器不成功,就会产生一个FileNotFoundException(文件未找到违例)。必须单独捕获这个违例——这属于我们不想关闭文件的一种特殊情况,因为文件尚未成功打开。其他任何捕获从句(catch)都必须关闭文件,因为文件已在进入那些捕获从句时打开(当然,如果多个方法都能产生一个FileNotFoundException 违例,就需要稍微用一些技巧。此时,我们可将不同的情况分隔到数个try 块内)。close()方法会掷出一个尝试过的违例。即使它在另一个catch 从句的代码块内,该违例也会得以捕获——对Java 编译器来说,那个catch 从句不过是另一对花括号而已。执行完本地操作后,违例会被重新“掷”出。这样做是必要的,因为这个构建器的执行已经失败,我们不希望调用方法来假设对象已正确创建以及有效。
在这个例子中,没有采用前述的标志技术,finally 从句显然不是关闭文件的正确地方,因为这可能在每次构建器结束的时候关闭它。由于我们希望文件在InputFile 对象处于活动状态时一直保持打开状态,所以这样做并不恰当。
getLine()方法会返回一个字串,其中包含了文件中下一行的内容。它调用了readLine(),后者可能产生一个违例,但那个违例会被捕获,使getLine()不会再产生任何违例。对违例来说,一项特别的设计问题是决定在这一级完全控制一个违例,还是进行部分控制,并传递相同(或不同)的违例,或者只是简单地传递它。在适当的时候,简单地传递可极大简化我们的编码工作。getLine()方法会变成:
String getLine() throwsIOException {
return in.readLine();
}
但是当然,调用者现在需要对可能产生的任何IOException 进行控制。
用户使用完毕InputFile 对象后,必须调用cleanup()方法,以便释放由BufferedReader 以及/或者FileReader 占用的系统资源(如文件句柄)——注释⑥。除非InputFile 对象使用完毕,而且到了需要弃之不用的时候,否则不应进行清除。大家可能想把这样的机制置入一个finalize()方法内,但正如指出的那样,并非总能保证finalize()获得正确的调用(即便确定它会调用,也不知道何时开始)。这属于Java的一项缺陷——除内存清除之外的所有清除都不会自动进行,所以必须知会客户程序员,告诉他们有责任用finalize()保证清除工作的正确进行。
在C++里,“破坏器”可帮我们控制这一局面。
在Cleanup.java 中,我们创建了一个InputFile,用它打开用于创建程序的相同的源文件。同时一次读取该文件的一行内容,而且添加相应的行号。所有违例都会在main()中被捕获——尽管我们可选择更大的可靠性。
违例与Java 的编程具有很高的集成度,这主要是由于编译器会强制它们。只有知道了如何操作那些违例,才可更进一步地掌握编译器的知识。
- 29.JAVA编程思想——构建器
- 《Java编程思想》学习笔记(二)——构建Java类和Java程序
- java编程思想—chapter11.Zipcompress.java
- 《JAVA编程思想》读书笔记1——OOP思想
- 11.JAVA编程思想——枚举器
- 76.JAVA编程思想——观察器范式
- 《java编程思想》——代码
- java 编程思想——基础篇
- JAVA编程思想——复用类
- Java编程思想读书笔记——字符串
- Java编程思想——泛型
- Java编程思想——第五章
- Java编程思想——第六章
- Java编程思想——第七章
- Java编程思想——第八章
- Java编程思想——第九章
- Java编程思想——第十章
- Java编程思想——第十一章
- hibernate性能优化
- oracle应该注意的细节
- leetcode——89——Gray Code
- 28.JAVA编程思想——用finally清除
- FZU 2151 OOXX Game
- 29.JAVA编程思想——构建器
- strstr代码
- 30.JAVA编程思想——违例匹配
- 16.4.19 杭州某创业公司前端开发实习生面试分享(大神勿入)
- HDU1071
- 31.JAVA编程思想——JAVA IO系统输入和输出
- bzoj4537: [Hnoi2016]最小公倍数
- leetcode-3. Longest Substring Without Repeating Characters
- Java 中 & 和 && 的区别