`

java解惑你知多少(四)

    博客分类:
  • Java
 
阅读更多

异常

26. finally与中断

Java代码  收藏代码
  1. //该方法返回false  
  2. static boolean f() {  
  3.  try {  
  4.   return true;  
  5.  } finally {  
  6.   return false;  
  7.  }  
  8. }  

不要用return、break、continue或throw来退出finally语句块,并且千万不要允许受检查的异常传播到finally语句

块之外。也就是说不要在finally块内终止程序,而是执行完finally块后,要将控制权移交给try块,由try最终决定

怎样结束方法的调用。

 

对于任何在finally语句块中可能抛出的受检查异常都要进行处理,而不是任其传播,下面流拷贝程序在关闭流时没有

防止异常的传播,这会有问题:

Java代码  收藏代码
  1. static void copy(String src, String dest) throws IOException {  
  2.  InputStream in = null;  
  3.  OutputStream out = null;  
  4.  try {  
  5.   in = new FileInputStream(src);  
  6.   out = new FileOutputStream(dest);  
  7.   byte[] buf = new byte[1024];  
  8.   int n;  
  9.   while ((n = in.read(buf)) >= 0) {  
  10.    out.write(buf, 0, n);  
  11.   }  
  12.  } finally{  
  13.   //这里应该使用try-catch将每个close包装起来  
  14.   if(in != null){in.close();}  
  15.   if(in != null){out.close();}  
  16.  }  
  17. }  

catch块中的return语句是不会阻止finally块执行的,那么catch块中的continue和break能否阻止?答案是不会的,

与return一样,finally语句块是在循环被跳过(continue)和中断(break)之前被执行的:

Java代码  收藏代码
  1. int i = 0;  
  2. System.out.println("--continue--");  
  3. while (i++ <= 1) {  
  4.  try {  
  5.   System.out.println("i=" + i);  
  6.   continue;  
  7.  } catch (Exception e) {  
  8.  } finally {  
  9.   System.out.println("finally");  
  10.  }  
  11. }  
  12. System.out.println("--break--");  
  13. while (i++ <= 3) {  
  14.  try {  
  15.   System.out.println("i=" + i);  
  16.   break;  
  17.  } catch (Exception e) {  
  18.  } finally {  
  19.   System.out.println("finally");  
  20.  }  
  21. }  

27. catch捕获异常规则

捕获RuntimeException、Exception或Throwable的catch语句是合法,不管try块里是否抛出了这三个异常。但如果try

块没有抛出或不可能抛出检测性异常,则catch不能捕获这些异常,如IOException异常:

Java代码  收藏代码
  1. public class Test {  
  2.  public static void main(String[] args) {  
  3.   try{  
  4.    //...  
  5.   }catch (Exception e) {  
  6.      
  7.   }catch (Throwable e) {  
  8.      
  9.   }  
  10.     
  11.   /* !! 编译出错 
  12.    try{ 
  13.     //... 
  14.    }catch (IOException e) { 
  15.      
  16.    } 
  17.    */  
  18.  }  
  19. }  

28. 重写时方法异常范围

重写或实现时不能扩大异常的范围,如果是多继承,则异常取所有父类方法异常的交集或不抛出异常:

Java代码  收藏代码
  1. interface I1 {  
  2.  void f() throws Exception;  
  3. }  
  4.   
  5. interface I2 {  
  6.  void f() throws IOException;  
  7. }  
  8.   
  9. interface I3 extends I1, I2 {}  
  10.   
  11. class Imp implements I3 {  
  12.  // 不能编译通过,多继承时只能取父类方法异常交集,这样就不会扩大异常范围  
  13.  // !! void f () throws Exception;  
  14.  // void f();// 能编译通过  
  15.  // 能编译通过,Exception与IOException的交集为IOException  
  16.  public void f() throws IOException {  
  17.  }  
  18. }  

29. 静态与非静态final常量不能在catch块中初始化

 

静态与非静态块中如果抛出了异常,则一定要使用try-catch块来捕获。

Java代码  收藏代码
  1. public class Test {  
  2.  static final int i;  
  3.  static {  
  4.   try {  
  5.    i = f();  
  6.   } catch (RuntimeException e) {  
  7.    i = 1;  
  8.   }  
  9.  }  
  10.   
  11.  static int f() {  
  12.   throw new RuntimeException();  
  13.  }  
  14. }  

上面的程序编译不能通过。表面上是可以的,因为i第一次初始化时可能抛出异常,所以抛异常时可以在catch块中初

始化,最终还是只初始化一次,这正是空final所要求的,但为什么编译器不知道这些呢?

 

要确定一个程序是否不止一次地对一个空final进行赋值是很困难的问题。语言规范在这一点上采用了保守的方式。

30. System.exit()与finally

Java代码  收藏代码
  1. try {  
  2.  System.out.println("Hello world");  
  3.  System.exit(0);  
  4.  // 或者使用Runtime退出系统  
  5.  // Runtime.getRuntime().exit(0);  
  6. finally {  
  7.  System.out.println("Goodbyte world");  
  8. }  

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

 

System.exit将立即停止所有的程序线程,它并不会使finally语句块得到调用,但是它在停止VM之前会执行关闭挂钩

操作(这此挂钩操作是注册到Runtime.addShutdownHook上的线程),这对于释放VM之外的资源很有帮助。使用挂钩程

序修改上面程序:

Java代码  收藏代码
  1. System.out.println("Hello world");  
  2. Runtime.getRuntime().addShutdownHook(new Thread() {  
  3.  public void run() {  
  4.   System.out.println("Goodbyte world");  
  5.  }  
  6. });  
  7. System.exit(0);  

 

另外,对象回收时,使用VM调用对象的finalize()方法有两种:
System.runFinalization():该方法让虚拟机也只是尽最大努力去完成所有未执行的finalize()终止方法,但不一定

会执行。
System.runFinalizersOnExit(true):该方法一定会回收,但不安全,已被废弃。因为它可能对正在使用的对象调用

终结方法,而其他线程同时正在操作这些对象,从而导致不正确的行为或死锁。

 

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

Runtime.getRuntime().gc()。

 

System的很多方法都是调用Runtime类的相关方法来实现的。


31. 递归构造

Java代码  收藏代码
  1. public class S  {  
  2.  private S instance = new S();  
  3.  public S() {}  
  4. }  

如果在程序外面构造该类的实例,则会抛出java.lang.StackOverflowError错误。其原因是实例变量的初始化操作将

先于构造器的程序体而运行。


32. 构造器中的异常

如果父类构造器抛出了检测异常,则子类也只能抛出,而不能采用try-catch来捕获:

Java代码  收藏代码
  1. public class P {  
  2.  public P() throws Exception {}  
  3. }  
  4.   
  5. class S extends P {  
  6.  public S() throws Exception {  
  7.   try {  
  8.    // 不能在try块中明确调用父类构造器,因为构造的  
  9.    // 明确调用只能放在第一行  
  10.    // !! super();  
  11.   //try-catch不能捕获到父类构造器所抛出的异常,子类只能抛出  
  12.   } catch (Exception e) {  
  13.   }  
  14.  }  
  15. }  

 
如果初使化实例属性时抛出了异常,则构造器只能抛出异常,在构造器中捕获不起作用:

Java代码  收藏代码
  1. public class A {  
  2.     private String str = String.class.newInstance();  
  3.   
  4.     public A() throws InstantiationException, IllegalAccessException {}  
  5.   
  6.     public A(int i) throws Exception {  
  7.         try {//即使这里捕获了,方法签名还是得要抛出  
  8.   
  9.         } catch (Exception e) {  
  10.   
  11.         }  
  12.     }  
  13.   
  14.     /* 
  15.      * !!编译不能通过,因为str2为静态的,他不能通过构造器来捕获,所以只 
  16.      * 能使用静态方法来捕获。即初始化静态成员时不能抛出捕获性异常。  
  17.      */  
  18.     //!!private static String str2 = String.class.newInstance();  
  19.       
  20.     // 只能使用静态方法来捕获异常,如果是抛出的运行时异常则不需要捕获  
  21.     private static String str2 = newInstance();  
  22.   
  23.     private static String newInstance() throws RuntimeException {  
  24.         try {  
  25.             return String.class.newInstance();  
  26.         } catch (Exception e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.         return null;  
  30.     }  
  31. }  

33. StackOverflowError

Java虚拟机对栈的深度限制到了某个值,当超过这个值时,VM就抛出StackOverflowError。一般VM都将栈的深度限制

为1024,即当方法调用方法的层次超过1024时就会产生StackOverflowError。

分享到:
评论

相关推荐

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

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

    java 解惑 java 解惑 java 解惑

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

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

    《Java解惑(中文版)》是一本专为Java初学者设计的学习资料,旨在帮助读者解答在学习Java过程中遇到的各种困惑。"solve65p"可能代表这本书包含65个问题或主题,每个都深入浅出地进行了讲解,旨在解决初学者在编程...

    Java PUZZLE Java 解惑

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

    Java解惑 中文版

    《Java解惑中文版》是一本专为Java程序员设计的指南,旨在帮助读者解决在编程过程中遇到的各种问题,提升程序的健壮性。本书深入浅出地探讨了Java语言的核心概念、常见疑惑以及最佳实践,旨在使开发者能够编写出更...

    JAVA 解惑 java经典

    "JAVA解惑"的主题针对的是Java学习过程中遇到的一些常见问题和难点,旨在帮助开发者深入理解和解决这些问题。以下是基于这个主题和描述可能涵盖的一些关键知识点: 1. **Java基础**:这可能包括变量、数据类型、...

    Java解惑.pdf

    这份“Java解惑.pdf”文档很可能包含了解决Java开发者在编程过程中遇到的常见问题和困惑的详细解答。以下是可能涵盖的一些Java相关知识点: 1. **基础语法**:Java的基础语法包括变量、数据类型、运算符、流程控制...

    "java解惑" PDF版本

    "java解惑" PDF版本

    java解惑 PDF版

    文档《java解惑 PDF版》中列举了95个这样的谜题,每个谜题都旨在帮助开发者理解并纠正一些常见的错误理解。以下是根据提供的部分内容解析的几个相关知识点。 ### 表达式谜题与取余操作符(%)的行为 在Java中,...

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

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

    JAVA解惑.pdf

    《JAVA解惑》这本书主要针对Java编程中遇到的各种常见问题和困惑进行了解答,旨在帮助开发者深入理解Java语言,提高编程技巧。以下是一些关键的知识点解析: 1. **异常处理**:Java中的异常处理是通过try-catch-...

    4,JAVA解惑 高清PDF 下载

    《JAVA解惑》是Java开发者领域的一本经典著作,它被广大...总之,《JAVA解惑》是一本涵盖了Java核心知识点、实战技巧和高级特性的宝典,无论你是Java新手还是老手,都能从中受益匪浅,解决你在Java编程中的种种疑惑。

    java解惑java解惑java解惑

    "Java解惑"这个主题,显然旨在帮助开发者解决他们在学习和实践中遇到的问题。在Java的世界里,疑惑可能涵盖语法、类库、框架、并发、内存管理等多个方面。下面,我们将深入探讨一些常见的Java解惑知识点。 1. **...

    java解惑 for all javaer

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

    JAVA解惑.pfd

    JAVA解惑

    java解惑(包括pdf和答案)

    "java解惑"这个主题旨在帮助初学者理解和解决在学习Java过程中遇到的问题,通过实例来深入浅出地讲解Java的基础知识,同时也强调了实用技巧和注意事项。 "Java解惑"的资料可能包含了两部分:`.chm`和`.pdf`格式的...

    Java解惑(中文).pdf

    《Java解惑(中文)》是一本专门为Java开发者编写的指南书籍,旨在解决在实际编程过程中遇到的各种疑惑和难题。本书以中文语言呈现,使得国内的Java程序员能够更轻松地理解并应用其中的知识。通过阅读这本书,读者...

    Java解惑(中文).pdf

    "Java解惑(中文).pdf"这份文档很显然是为了帮助Java开发者解决他们在编程过程中遇到的一些常见困惑和误解。这份高清版、文字版的资料很可能包含了深入浅出的解释和实例分析,以中文的形式呈现,使得国内开发者更容易...

Global site tag (gtag.js) - Google Analytics