隨筆-204  評(píng)論-149  文章-0  trackbacks-0
          RuntimeException異常以及其子類異常,不需要異常說明就可以從任何地方拋出
          是uncheck exception。

          從程序的輸出看出,無論有沒有拋出異常,finally子句總會(huì)得到執(zhí)行,
          這個(gè)程序也啟發(fā)我們應(yīng)該如何處理我們前面講到過的,Java異常(和C
          ++
          的異常一樣)會(huì)阻止程序回到異常拋出的地方恢復(fù)執(zhí)行這個(gè)問題。
          如果你把try塊放進(jìn)一個(gè)循環(huán),你就能構(gòu)建一個(gè)程序運(yùn)行之前必須滿足的條件。

          class ThreeException extends Exception{
              
          }

          public class FinallyWorks {

              
              
          static int count = 0;
              
              
          public static void main(String[] args) {
                  
          while(true){
                      
          try{
                          
          if(count++==0){
                              
          throw new ThreeException();
                          }

                          System.out.println(
          "No Exception");
                      }
          catch(Exception e){
                          System.err.println(
          "ThreeException");
                      }
          finally{
                          System.err.println(
          "In finally clause");
                          
          if(count==2)
                              
          break;
                      }

                  }

              }


          }


          ThreeException
          In 
          finally clause
          No Exception
          In 
          finally clause





          Finally子句的執(zhí)行
          class FourException extends Exception {
          }


          public class AlwaysFinally {

              
          public static void main(String[] args){
                  System.out.println(
          "Entering first try block");
                  
          try {
                      System.out.println(
          "Entering second try block");
                      
          try {
                          
          throw new FourException();
                      }
           finally {
                          System.out.println(
          "finally in 2nd try block");
                      }

                  }
           catch (FourException e) {
                      System.err.println(
          "Caught FourException in 1st try block");
                  }
           finally {
                      System.err.println(
          "finally in 1st try block");
                  }


              }

          }

          Entering first 
          try block
          Entering second 
          try block
          finally in 2nd try block
          Caught FourException in 1st 
          try block
          finally in 1st try block





          丟失的異常
          package exceptiontest;

          class VeryImportantException extends Exception {
              
          public String toString() {
                  
          return "A very important exception!";
              }

          }


          class HoHumException extends Exception {
              
          public String toString() {
                  
          return "A trivial exception";
              }

          }


          public class LostMessage {
              
          void f() throws VeryImportantException {
                  
          throw new VeryImportantException();
              }


              
          void dispose() throws HoHumException {
                  
          throw new HoHumException();
              }


              
          public static void main(String[] args) throws Exception {
                  LostMessage lm 
          = new LostMessage();
                  
          try {
                      lm.f();
                  }
           finally {
                      lm.dispose();
                  }


              }

          }


          看到了嗎?VeryImportantException消失的無影無蹤了,它直接被finally里面的HoHumException給取代了,這是一個(gè)相當(dāng)嚴(yán)重的錯(cuò)誤,它表示這個(gè)異常被徹底丟失了,而在真實(shí)環(huán)境中,這種情況會(huì)遠(yuǎn)比上述程序更為微妙,更難以察覺。相反,C
          ++會(huì)把這種“第一個(gè)異常尚未得到處理,就產(chǎn)生了第二個(gè)異常”的現(xiàn)象,當(dāng)成極端嚴(yán)重的編程錯(cuò)誤。







          //Java構(gòu)造函數(shù)中發(fā)生的異常
          class InputFile {
              
          private BufferedReader in;

              
          public 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; // Rethrow
                  }
           finally {
                      
          // Don't close it here!!!
                  }

              }


              
          public String getLine() {
                  String s;
                  
          try {
                      s 
          = in.readLine();
                  }
           catch (IOException e) {
                      
          throw new RuntimeException("readLine() failed");
                  }

                  
          return s;
              }


              
          public void dispose() {
                  
          try {
                      in.close();
                      System.out.println(
          "dispose() successful");
                  }
           catch (IOException e2) {
                      
          throw new RuntimeException("in.close() failed");
                  }

              }

          }


          public class Cleanup {
              
          private static Test monitor = new Test();

              
          public static void main(String[] args) {
                  
          try {
                      InputFile in 
          = new InputFile("Cleanup.java");
                      String s;
                      
          int i = 1;
                      
          while ((s = in.getLine()) != null)
                          ; 
          // Perform line-by-line processing here
                      in.dispose();
                  }
           catch (Exception e) {
                      System.err.println(
          "Caught Exception in main");
                      e.printStackTrace();
                  }

                  monitor.expect(
          new String[] "dispose() successful" });
              }

          }
           // /:~



          異常處理系統(tǒng)還是一扇能讓你放棄程序正常運(yùn)行順序的暗門。當(dāng)某種“異常情況”出現(xiàn)的時(shí)候,這個(gè)門就開啟了,于是程序再也不能,或者再也不按照正常的順序執(zhí)行下去。異常表示的是一些“當(dāng)前方法無法處理”的情況。之所以要開發(fā)異常處理系統(tǒng),是因?yàn)橐獙?duì)每次函數(shù)調(diào)用的每個(gè)錯(cuò)誤做檢查實(shí)在是太費(fèi)力了,所以程序員根本就不去做。結(jié)果就是把錯(cuò)誤給忽略了。
          異常處理的一個(gè)重要準(zhǔn)則就是“如果你不知道該如何處理這個(gè)異常,你就別去捕捉它”。實(shí)際上,異常處理有一項(xiàng)重要的目標(biāo),這就是將處理異常的代碼從異常發(fā)生的地方移開。這樣你就能在一個(gè)地方集中精力去解決你想解決的問題,然后再到另外一個(gè)地方處理這些異常問題了。
          但是 java所特有的checked exception將這種情況變的稍微復(fù)雜些了,這是因?yàn)榧词鼓悴粶?zhǔn)備這么做,編譯器也強(qiáng)制要求你在try的后面加上catch子句,于是這就導(dǎo)致了“錯(cuò)誤地私吞harmful 
          if swallowed”的問題了:


          注意一下throw e.fillInStackTrace();的用法

          package exceptiontest;

          import java.util.Collections;

          public class Rethrowing {
              
          public static void f()throws Exception{
                  System.err.println(
          "originating the exception n f()");
                  
          throw new Exception("throw from f()");
              }

              
          public static void g()throws Throwable{
                  
          try{
                      f();
                  }
          catch(Exception e){
                      System.err.println(
          "Inside g(),e.printlStackTrace()");
                      e.printStackTrace();
                      
          //throw e;
                      throw e.fillInStackTrace();
                  }

                  
              }

              
          public static void h()throws Exception{
                  f();
              }

              
          public static void main(String[] args)throws Throwable{
                  
          try{
                      g();
                  }
          catch(Exception e){
                      System.err.println(
          "Caught in main,e.printStackTrace");
                      e.printStackTrace();
                  }

              }


          }

          運(yùn)行結(jié)果:
          originating the exception n f()
          Inside g(),e.printlStackTrace()
          java.lang.Exception: throw from f()
           at exceptiontest.Rethrowing.f(Rethrowing.java:8)
           at exceptiontest.Rethrowing.g(Rethrowing.java:12)
           at exceptiontest.Rethrowing.main(Rethrowing.java:26)
          Caught in main,e.printStackTrace
          java.lang.Exception: throw from f()
           at exceptiontest.Rethrowing.g(Rethrowing.java:17)
           at exceptiontest.Rethrowing.main(Rethrowing.java:26)


          如不使用 throw e.fillInStackTrace(),而是throw e
          originating the exception n f()
          Inside g(),e.printlStackTrace()
          java.lang.Exception: throw from f()
           at exceptiontest.Rethrowing.f(Rethrowing.java:8)
           at exceptiontest.Rethrowing.g(Rethrowing.java:12)
           at exceptiontest.Rethrowing.main(Rethrowing.java:26)
          Caught in main,e.printStackTrace
          java.lang.Exception: throw from f()
           at exceptiontest.Rethrowing.f(Rethrowing.java:8)
           at exceptiontest.Rethrowing.g(Rethrowing.java:12)
           at exceptiontest.Rethrowing.main(Rethrowing.java:26)



          Exception chaining

          Often you want to catch one exception and throw another, but still keep the information about the originating exception—this is called exception chaining. Prior to JDK 1.4, programmers had to write their own code to preserve the original exception information, but now all Throwable subclasses may take a cause object in their constructor. The cause is intended to be the originating exception, and by passing it in you maintain the stack trace back to its origin, even though you’re creating and throwing a new exception at this point.

          It’s interesting to note that the only Throwable subclasses that provide the cause argument in the constructor are the three fundamental exception classes Error (used by the JVM to report system errors), Exception, and RuntimeException. If you want to chain any other exception types, you do it through the initCause( ) method rather than the constructor.

          //: c09:DynamicFields.java
          // A Class that dynamically adds fields to itself.
          // Demonstrates exception chaining.
          // {ThrowsException}
          import com.bruceeckel.simpletest.*;

          class DynamicFieldsException extends Exception {}

          public class DynamicFields {
            
          private static Test monitor = new Test();
            
          private Object[][] fields;
            
          public DynamicFields(int initialSize) {
              fields 
          = new Object[initialSize][2];
              
          for(int i = 0; i < initialSize; i++)
                fields[i] 
          = new Object[] nullnull };
            }

            
          public String toString() {
              StringBuffer result 
          = new StringBuffer();
              
          for(int i = 0; i < fields.length; i++{
                result.append(fields[i][
          0]);
                result.append(
          "");
                result.append(fields[i][
          1]);
                result.append(
          "\n");
              }

              
          return result.toString();
            }

            
          private int hasField(String id) {
              
          for(int i = 0; i < fields.length; i++)
                
          if(id.equals(fields[i][0]))
                  
          return i;
              
          return -1;
            }

            
          private int
            getFieldNumber(String id) 
          throws NoSuchFieldException {
              
          int fieldNum = hasField(id);
              
          if(fieldNum == -1)
                
          throw new NoSuchFieldException();
              
          return fieldNum;
            }

            
          private int makeField(String id) {
              
          for(int i = 0; i < fields.length; i++)
                
          if(fields[i][0== null{
                  fields[i][
          0= id;
                  
          return i;
                }

              
          // No empty fields. Add one:
              Object[][]tmp = new Object[fields.length + 1][2];
              
          for(int i = 0; i < fields.length; i++)
                tmp[i] 
          = fields[i];
              
          for(int i = fields.length; i < tmp.length; i++)
                tmp[i] 
          = new Object[] nullnull };
              fields 
          = tmp;
              
          // Reursive call with expanded fields:
              return makeField(id);
            }

            
          public Object
            getField(String id) 
          throws NoSuchFieldException {
              
          return fields[getFieldNumber(id)][1];
            }

            
          public Object setField(String id, Object value)
            
          throws DynamicFieldsException {
              
          if(value == null{
                
          // Most exceptions don't have a "cause" constructor.
                
          // In these cases you must use initCause(),
                
          // available in all Throwable subclasses.
                DynamicFieldsException dfe =
                  
          new DynamicFieldsException();
                dfe.initCause(
          new
           NullPointerException());
                
          throw
           dfe;
              }

              
          int fieldNumber = hasField(id);
              
          if(fieldNumber == -1)
                fieldNumber 
          = makeField(id);
              Object result 
          = null;
              
          try {
                result 
          = getField(id); // Get old value
              }
           catch(NoSuchFieldException e) {
                
          // Use constructor that takes "cause":
                throw new RuntimeException(e);
              }

              fields[fieldNumber][
          1= value;
              
          return result;
            }

            
          public static void main(String[] args) {
              DynamicFields df 
          = new DynamicFields(3);
              System.out.println(df);
              
          try {
                df.setField(
          "d""A value for d");
                df.setField(
          "number"new Integer(47));
                df.setField(
          "number2"new Integer(48));
                System.out.println(df);
                df.setField(
          "d""A new value for d");
                df.setField(
          "number3"new Integer(11));
                System.out.println(df);
                System.out.println(df.getField(
          "d"));
                Object field 
          = df.getField("a3"); // Exception
              }
           catch(NoSuchFieldException e) {
                
          throw new RuntimeException(e);
              }
           catch(DynamicFieldsException e) {
                
          throw new RuntimeException(e);
              }

              monitor.expect(
          new String[] {
                
          "null: null",
                
          "null: null",
                
          "null: null",
                
          "",
                
          "d: A value for d",
                
          "number: 47",
                
          "number2: 48",
                
          "",
                
          "d: A new value for d",
                
          "number: 47",
                
          "number2: 48",
                
          "number3: 11",
                
          "",
                
          "A value for d",
                
          "Exception in thread \"main\" " +
                
          "java.lang.RuntimeException: " +
                
          "java.lang.NoSuchFieldException",
                
          "\tat DynamicFields.main(DynamicFields.java:98)",
                
          "Caused by: java.lang.NoSuchFieldException",
                
          "\tat DynamicFields.getFieldNumber(" +
                
          "DynamicFields.java:37)",
                
          "\tat DynamicFields.getField(DynamicFields.java:58)",
                
          "\tat DynamicFields.main(DynamicFields.java:96)"
              }
          );
            }

          }
           ///:~




          方法覆蓋時(shí)異常的情況
          package exceptiontest;
          //方法覆蓋時(shí)異常的情況
          //: c09:StormyInning.java
          //Overridden methods may throw only the exceptions
          //specified in their base-class versions, or exceptions
          //derived from the base-class exceptions.

          class BaseballException extends Exception {
          }


          class Foul extends BaseballException {
          }


          class Strike extends BaseballException {
          }


          abstract class Inning {
              
          public Inning() throws BaseballException {
              }


              
          public void event() throws BaseballException {
                  
          // Doesn't actually have to throw anything
              }


              
          public abstract void atBat() throws Strike, Foul;

              
          public void walk() {
              }
           // Throws no checked exceptions
          }


          class StormException extends Exception {
          }


          class RainedOut extends StormException {
          }


          class PopFoul extends Foul {
          }


          interface Storm {
              
          public void event() throws RainedOut;

              
          public void rainHard() throws RainedOut;
          }


          public class StormyInning extends Inning implements Storm {
              
          // OK to add new exceptions for constructors, but you
              
          // must deal with the base constructor exceptions:
              
          //構(gòu)造函數(shù)可以多,但是它必須加基類構(gòu)造函數(shù)所聲明的異常
              public StormyInning() throws RainedOut, BaseballException {
              }


              
          public StormyInning(String s) throws Foul, BaseballException {
              }


              
          // Regular methods must conform to base class:
              
          //異常聲明只少不多,但這種異常方面的限制對(duì)構(gòu)造函數(shù)不起作用
              
          // ! void walk() throws PopFoul {} //Compile error
              
          // Interface CANNOT add exceptions to existing
              
          // methods from the base class:以基類為準(zhǔn)而不是以接口為準(zhǔn)
              
          // ! public void event() throws RainedOut {}
              
          // If the method doesn't already exist in the
              
          // base class, the exception is OK:
              public void rainHard() throws RainedOut {
              }


              
          // You can choose to not throw any exceptions,
              
          // even if the base version does:
              
          //異常聲明只少不多*****************************
              public void event() {
              }


              
          // Overridden methods can throw inherited exceptions:
              public void atBat() throws PopFoul {
              }


              
          public static void main(String[] args) {
                  
          try {
                      StormyInning si 
          = new StormyInning();
                      si.atBat();
                  }
           catch (PopFoul e) {
                      System.err.println(
          "Pop foul");
                  }
          catch(Foul e){
                      
                  }
          catch (RainedOut e) {
                      System.err.println(
          "Rained out");
                  }
           catch (BaseballException e) {
                      System.err.println(
          "Generic baseball exception");
                  }

                  
          // Strike not thrown in derived version.
                  try {
                      
          // What happens if you upcast?
                      Inning i = new StormyInning();
                      i.atBat();
                      
          // You must catch the exceptions from the
                      
          // base-class version of the method:
                  }
           catch (Strike e) {
                      System.err.println(
          "Strike");
                  }
           catch (Foul e) {
                      System.err.println(
          "Foul");
                  }
           catch (RainedOut e) {
                      System.err.println(
          "Rained out");
                  }
           catch (BaseballException e) {
                      System.err.println(
          "Generic baseball exception");
                  }

              }

          }

          posted on 2009-06-18 23:40 Frank_Fang 閱讀(1016) 評(píng)論(0)  編輯  收藏 所屬分類: Java編程
          主站蜘蛛池模板: 丰原市| 瓮安县| 老河口市| 湖北省| 宁武县| 济宁市| 尚义县| 淮安市| 高陵县| 明星| 公主岭市| 宿迁市| 仁寿县| 阳新县| 咸阳市| 吐鲁番市| 承德县| 萨嘎县| 竹山县| 江山市| 句容市| 黑龙江省| 广德县| 舟山市| 伽师县| 乐山市| 长海县| 思南县| 苏尼特右旗| 成都市| 闻喜县| 西华县| 竹北市| 洛阳市| 陕西省| 北辰区| 河间市| 东至县| 岳西县| 浙江省| 明光市|