`

Java 解惑知多少四

阅读更多
26. finally与中断
//该方法返回false  
static boolean f() {  
 try {  
  return true;  
 } finally {  
  return false;  
 }  
}  

不要用return、break、continue或throw来退出finally语句块,并且千万不要允许受检查的异常传播到finally语句
块之外。也就是说不要在finally块内终止程序,而是执行完finally块后,要将控制权移交给try块,由try最终决定
怎样结束方法的调用。

对于任何在finally语句块中可能抛出的受检查异常都要进行处理,而不是任其传播,下面流拷贝程序在关闭流时没有
防止异常的传播,这会有问题:
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, 0, n);  
  }  
 } finally{  
  //这里应该使用try-catch将每个close包装起来  
  if(in != null){in.close();}  
  if(in != null){out.close();}  
 }  
}  

catch块中的return语句是不会阻止finally块执行的,那么catch块中的continue和break能否阻止?答案是不会的,
与return一样,finally语句块是在循环被跳过(continue)和中断(break)之前被执行的:
int i = 0;  
System.out.println("--continue--");  
while (i++ <= 1) {  
 try {  
  System.out.println("i=" + i);  
  continue;  
 } catch (Exception e) {  
 } finally {  
  System.out.println("finally");  
 }  
}  
System.out.println("--break--");  
while (i++ <= 3) {  
 try {  
  System.out.println("i=" + i);  
  break;  
 } catch (Exception e) {  
 } finally {  
  System.out.println("finally");  
 }  
}  

27. catch捕获异常规则
捕获RuntimeException、Exception或Throwable的catch语句是合法,不管try块里是否抛出了这三个异常。但如果try
块没有抛出或不可能抛出检测性异常,则catch不能捕获这些异常,如IOException异常:
public class Test {  
 public static void main(String[] args) {  
  try{  
   //...  
  }catch (Exception e) {  
     
  }catch (Throwable e) {  
     
  }  
    
  /* !! 编译出错 
   try{ 
    //... 
   }catch (IOException e) { 
     
   } 
   */  
 }  
}  

28. 重写时方法异常范围
重写或实现时不能扩大异常的范围,如果是多实现,则异常取所有父类方法异常的交集或不抛出异常:
interface I1 {  
 void f() throws Exception;  
}  
  
interface I2 {  
 void f() throws IOException;  
}  
  
interface I3 extends I1, I2 {}  
  
class Imp implements I3 {  
 // 不能编译通过,多继承时只能取父类方法异常交集,这样就不会扩大异常范围  
 // !! void f () throws Exception;  
 // void f();// 能编译通过  
 // 能编译通过,Exception与IOException的交集为IOException  
 public void f() throws IOException {  
 }  
}  

29. 静态与非静态final常量不能在catch块中初始化
静态与非静态块中如果抛出了异常,则一定要使用try-catch块来捕获。
public class Test {  
 static final int i;  
 static {  
  try {  
   i = f();  
  } catch (RuntimeException e) {  
   i = 1;  
  }  
 }  
  
 static int f() {  
  throw new RuntimeException();  
 }  
}  

上面的程序编译不能通过。表面上是可以的,因为i第一次初始化时可能抛出异常,所以抛异常时可以在catch块中初
始化,最终还是只初始化一次,这正是空final所要求的,但为什么编译器不知道这些呢?

要确定一个程序是否不止一次地对一个空final进行赋值是很困难的问题。语言规范在这一点上采用了保守的方式。
30. System.exit()与finally
try {  
 System.out.println("Hello world");  
 System.exit(0);  
 // 或者使用Runtime退出系统  
 // Runtime.getRuntime().exit(0);  
} finally {  
 System.out.println("Goodbyte world");  
}  

上面的程序会打印出"Goodbyte world"吗?不会。

System.exit将立即停止所有的程序线程,它并不会使finally语句块得到调用,但是它在停止VM之前会执行关闭挂钩
操作(这此挂钩操作是注册到Runtime.addShutdownHook上的线程),这对于释放VM之外的资源很有帮助。使用挂钩程
序修改上面程序:
System.out.println("Hello world");  
Runtime.getRuntime().addShutdownHook(new Thread() {  
 public void run() {  
  System.out.println("Goodbyte world");  
 }  
});  
System.exit(0); 

另外,对象回收时,使用VM调用对象的finalize()方法有两种:
System.runFinalization():该方法让虚拟机也只是尽最大努力去完成所有未执行的finalize()终止方法,但不一定
会执行。
System.runFinalizersOnExit(true):该方法一定会回收,但不安全,已被废弃。因为它可能对正在使用的对象调用
终结方法,而其他线程同时正在操作这些对象,从而导致不正确的行为或死锁。

为了加快垃圾回收,使用System.gc(),但不一定马上执行加收动作,由虚拟机决定,实质上是调用
Runtime.getRuntime().gc()。

System的很多方法都是调用Runtime类的相关方法来实现的。
31. 递归构造
public class S  {  
 private S instance = new S();  
 public S() {}  
}  

如果在程序外面构造该类的实例,则会抛出java.lang.StackOverflowError错误。其原因是实例变量的初始化操作将
先于构造器的程序体而运行。
32. 构造器中的异常
如果父类构造器抛出了检测异常,则子类也只能抛出,而不能采用try-catch来捕获:
public class P {  
 public P() throws Exception {}  
}  
  
class S extends P {  
 public S() throws Exception {  
  try {  
   // 不能在try块中明确调用父类构造器,因为构造的  
   // 明确调用只能放在第一行  
   // !! super();  
  //try-catch不能捕获到父类构造器所抛出的异常,子类只能抛出  
  } catch (Exception e) {  
  }  
 }  
}  

如果初使化实例属性时抛出了异常,则构造器只能抛出异常,在构造器中捕获不起作用:
public class A {  
    private String str = String.class.newInstance();  
  
    public A() throws InstantiationException, IllegalAccessException {}  
  
    public A(int i) throws Exception {  
        try {//即使这里捕获了,方法签名还是得要抛出  
  
        } catch (Exception e) {  
  
        }  
    }  
  
    /* 
     * !!编译不能通过,因为str2为静态的,他不能通过构造器来捕获,所以只 
     * 能使用静态方法来捕获。即初始化静态成员时不能抛出捕获性异常。  
     */  
    //!!private static String str2 = String.class.newInstance();  
      
    // 只能使用静态方法来捕获异常,如果是抛出的运行时异常则不需要捕获  
    private static String str2 = newInstance();  
  
    private static String newInstance() throws RuntimeException {  
        try {  
            return String.class.newInstance();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return null;  
    }  
}  

33. StackOverflowError
Java虚拟机对栈的深度限制到了某个值,当超过这个值时,VM就抛出StackOverflowError。一般VM都将栈的深度限制
为1024,即当方法调用方法的层次超过1024时就会产生StackOverflowError。

ref:http://jiangzhengjun.iteye.com/blog/652720
分享到:
评论

相关推荐

    java解惑java解惑java解惑

    java解惑java解惑java解惑java解惑java解惑java解惑

    Java解惑Java解惑

    Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑

    Java解惑.pdf

    Java解惑.pdf Java解惑.pdf Java解惑.pdf Java解惑.pdf

    Java解惑 中文版

    Java解惑中文版 Java解惑 java健壮程序

    JAVA解惑.pdf

    JAVA解惑.pdf JAVA解惑.pdf JAVA解惑.pdf

    java解惑(+Java 解惑你知多少)

    你认为自己了解Java多少?你是个爱琢磨的代码侦探吗?你是否曾经花费数天时间去追踪一个由Java或其类库的陷阱和缺陷而导致的bug?你喜欢智力测验吗?本书正好适合你!.. Bloch和Gafter继承了Effective Jaya一书的传统,...

    JAVA 解惑 java经典

    JAVA解惑,你面包括一些java经典的问题。

    Java PUZZLE Java 解惑

    Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑

    Java解惑(中文版)_java_java解惑_solve65p_

    与java相关的的学习,适合初学者,可以看看

    最新版的Java-解惑

    《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》

    Java解惑 布洛克 著;陈昊鹏 译

    《Java解惑》 布洛克 著;陈昊鹏 译 扫描清晰带目录,仅供参阅,请支持正版

    4,JAVA解惑 高清PDF 下载

    Java四大名著之一:4,JAVA解惑 高清PDF 下载

    "java解惑" PDF版本

    "java解惑" PDF版本

    java解惑 for all javaer

    讲述如何在程序中避免程序缺陷和程序陷阱的,解惑的过程中,介绍了一些Java编程语言中许多不易被掌握的知识点,其阅读价值非常高,适合具有Java知识的学习者和有编程经验的Java程序员阅读。

    Java解惑(中文).pdf

    Java解惑(中文).pdf 给大家介绍java中容易迷惑用错的实例

    JAVA解惑(JAVA谜题) 中文版(PDF)

    Java解惑,是一本以大量java实例,讲述如何在程序中避免程序缺陷和程序陷阱的,解惑的过程中,介绍了一些Java编程语言中许多不易被掌握的知识点,其阅读价值非常高,适合具有Java知识的学习者和有编程经验的Java...

    《Java Pazzlers》Java解惑.pdf 书签齐全

    该书特写了95个有关Java或其类库的陷阱和缺陷的谜题,其中大多数谜题都采用了短程序的方式,这些程序的行为与其看似的大相径庭。在每个谜题之后都给出了详细的解惑方案,这些解惑方案超越了对程序行为的简单解释,向...

    Java解惑(中文).pdf

    。。。。。 Java解惑(中文) 是一本对 Java一些问题的解答 。。。。。。。。。。

    Java解惑

    Java解惑,罗列你意想不到的100道java疑惑

Global site tag (gtag.js) - Google Analytics