[b]谜题41:域和流[/b]
下面的方法实现将一个文件拷贝到另一个文件,但它[color=red]并非总是能够做到[/color]这一点,为什么不能呢?如何修改?
问题在于finally自身,close方法也可能抛出IOException异常。如果正好发生在in.close()调用之时,就会阻止out.close 的调用,从而使输出流保持在开放状态。注意,该程序违反了谜题36的建议:[color=red]对close的调用可能会导致finally语句块意外结束[/color]。解决方式 是将每一个close都包含在一个嵌套的try语句块中。
[b]谜题42:异常为循环而抛[/b]
打印出0
这个程序犯了两个错误,第1个错误是该程序使用了一种可怕的循环惯用法。不要使用异常控制循环;应该只为异常条件而使用异常。
为纠正这个错误,将整个try-finally语句块替换为循环遍历数组的标准惯用法:
for(int i = 0;i<tests.length;i++){
if(thirdElemIsThree(tests[i]))count++;
}
再次运行,会出现java.lang.ArrayIndexOutOfBoundsException异常,因为&运算符要计算两个操作数,改用短路的&&运算符。return a.length>=3 [color=red]&&[/color] a[2] ==3;
[b]谜题43:异常的危险[/b]
在jdk1.2中,Thread.stop、Thread.suspend以及其他许多线程相关的方法都因为不安全而不推荐使用了。
[b]谜题44:删除类[/b]
[color=red]要想编写一个能够探测类丢失的程序,请使用反射[/color]来引用类而不是使用通常的语言结构。如下程序展示了这种技巧:
[color=red]总之,不要对捕捉NoClassDefFoundError形成依赖。更一般地讲,捕获Error及其子类型几乎是完全不恰当的。[/color]
本谜题测试你对递归的了解程度,下面的程序将做些什么呢?
要不是有try-finally语句,行为非常明显:workhard递归调用自身,直到程序抛出StackOverflowError异常。但这个程序一直的在循环。因为一般VM将栈的深度限制为1024,因此,调用的数量就是1+2+4+。。。=2^1025-1,而抛出异常的数量是2^1024,没人能看到这个程序终止的时刻。
下面的方法实现将一个文件拷贝到另一个文件,但它[color=red]并非总是能够做到[/color]这一点,为什么不能呢?如何修改?
static void copy(String src,String dest) throws IOException{
InputStream in =null;
OutputStream out = null;
try{
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int n;
while((n=in.read(buf))>=0){
out.write(buf);
}
}
finally{
if(in!=null) in.close();
if(out!=null)out.close();
}
}
问题在于finally自身,close方法也可能抛出IOException异常。如果正好发生在in.close()调用之时,就会阻止out.close 的调用,从而使输出流保持在开放状态。注意,该程序违反了谜题36的建议:[color=red]对close的调用可能会导致finally语句块意外结束[/color]。解决方式 是将每一个close都包含在一个嵌套的try语句块中。
[b]谜题42:异常为循环而抛[/b]
public class Loop {
public static void main(String[] args) {
int[][] tests = {{6,5,4,3,2,1},{1,2},{1,2,3},{1,2,3,4},{1}};
int count = 0;
try{
int i =0;
while(true){
if(thirdElemIsThree(tests[i++])) count ++;
}
}catch(ArrayIndexOutOfBoundsException e){
}
System.out.println(count);
}
private static boolean thirdElemIsThree(int[] a) {
return a.length>=3 & a[2] ==3;
}
}
打印出0
这个程序犯了两个错误,第1个错误是该程序使用了一种可怕的循环惯用法。不要使用异常控制循环;应该只为异常条件而使用异常。
为纠正这个错误,将整个try-finally语句块替换为循环遍历数组的标准惯用法:
for(int i = 0;i<tests.length;i++){
if(thirdElemIsThree(tests[i]))count++;
}
再次运行,会出现java.lang.ArrayIndexOutOfBoundsException异常,因为&运算符要计算两个操作数,改用短路的&&运算符。return a.length>=3 [color=red]&&[/color] a[2] ==3;
[b]谜题43:异常的危险[/b]
在jdk1.2中,Thread.stop、Thread.suspend以及其他许多线程相关的方法都因为不安全而不推荐使用了。
[b]谜题44:删除类[/b]
[color=red]要想编写一个能够探测类丢失的程序,请使用反射[/color]来引用类而不是使用通常的语言结构。如下程序展示了这种技巧:
try{
Object m = Class.forName("Missing").newInstance();
}catch(NoClassDefFoundError ex){
System.err.println("got it!");
}
[color=red]总之,不要对捕捉NoClassDefFoundError形成依赖。更一般地讲,捕获Error及其子类型几乎是完全不恰当的。[/color]
谜题45:令人疲惫不堪的测试
本谜题测试你对递归的了解程度,下面的程序将做些什么呢?
public class Workout {
public static void main(String[] args) {
workhard();
System.out.println("It's nap time");
}
private static void workhard() {
try{
workhard();
}finally{
workhard();
}
}
}
要不是有try-finally语句,行为非常明显:workhard递归调用自身,直到程序抛出StackOverflowError异常。但这个程序一直的在循环。因为一般VM将栈的深度限制为1024,因此,调用的数量就是1+2+4+。。。=2^1025-1,而抛出异常的数量是2^1024,没人能看到这个程序终止的时刻。