2013年12月21日 星期六

Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking
許裕永 譯 (原文內容取自 Oracle 官網)
This page covers the following topics:
Handling More Than One Type of Exception
Rethrowing Exceptions with More Inclusive Type Checking
本頁包含下列主題:Handling More Than One Type of Exception
Rethrowing Exceptions with More Inclusive Type Checking
Handling More Than One Type of Exception
In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.
處理一個以上型別的 Exception
在 Java SE7 及以後版本, 單一一個 catch 區塊可以處理一個以上型別的 Exception. 這個特色可以減少重複的程式碼以及降低 catch 過度廣泛的 exception 的誘因.


Consider the following example, which contains duplicate code in each of the catch blocks:
了解下列範例, 它包含了重複的程式碼在每一個 catch 區塊之中:
 catch (IOException ex) {
  logger.log(ex);
  throw ex;
 catch (SQLException ex) {
  logger.log(ex);
  throw ex;
 }

In releases prior to Java SE 7, it is difficult to create a common method to eliminate the duplicated code because the variable ex has different types.
在 Java SE 7 之前的版本, 因為變數 ex 代表著不同的型別, 所以很難建立一個公用方法來排除重複的程式碼.

The following example, which is valid in Java SE 7 and later, eliminates the duplicated code:
下列範例, 它在 Java SE7 及以後版本中是合法的, 它排除了重複的程式碼:
 catch (IOException | SQLException ex) {
  logger.log(ex);
  throw ex;
 }

The catch clause specifies the types of exceptions that the block can handle, and each exception type is separated with a vertical bar (|).
在 catch 條文中宣告這個區塊可以處理的所有 exceptions 的型別, 而且每一個 exception 的型別用直條線 (|) 區隔.

Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final. In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.
注意: 如果一個 catch 區塊處理了一個以上的 exception 型別, 那麼該 catch 中的參數將會隱含宣告為 final. 在這個範例中, catch 中的參數 ex 就是 final, 所以在這個 catch 區塊中, 你不可以指派任何值給它.

Bytecode generated by compiling a catch block that handles multiple exception types will be smaller (and thus superior) than compiling many catch blocks that handle only one exception type each. A catch block that handles multiple exception types creates no duplication in the bytecode generated by the compiler; the bytecode has no replication of exception handlers.
一個 catch 區塊處理多個型別的 exception, 在編譯後所產生的 bytecode, 將會比用多個 catch 區塊各自處理一個 exception 所產生的 bytecode 更少而且更優越. 一個 catch 區塊處理多個型別的 exception,  編譯器在產生 bytecode 時不會發生重複的情形; bytecode 中不會有重複的 exception 處理者.

Rethrowing Exceptions with More Inclusive Type Checking
The Java SE 7 compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.
Rethrowing Exceptions 時, 附加了對 exceptions 所包含的型別的檢查:

Consider the following example:
了解下列範例:

 static class FirstException extends Exception { }
 static class SecondException extends Exception { }

 public void rethrowException (String exceptionName) throws Exception {
  try {
   if (exceptionName.equals("First")) {
    throw new FirstException();
   } else {
    throw new SecondException();
   }
  } catch (Exception e) {
   throw e;
  }
 }

This examples's try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of the rethrowException method declaration.
這個範例的 try 區塊可能丟出 FirstException 或 SecondException. 假設你想要在 rethrowException 方法宣告時在它的 throws 條文中宣告這些 exception 的型別. 在 Java SE 7 之前的版本中, 你是無法辦到的. 因為在 catch條文中的 exception 參數 e 的型別是 Exception, 而且在 catch 區塊中 rethrows exception 參數 e, 你只能夠在宣告 rethrowException 方法時在 throws 條文中指定 exception 型別為 Exception.

However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException:
然而, 在 Java SE 7, 你可以在宣告 rethrowException 方法時, 指定 exception 的型別 FirstException 及 SecondException 在 throws 條文之中. Java SE 7 編譯器可以判定 exception 的被丟出必定是來自於 try 區塊中的敘述  throw e, 而且從 try 區塊中丟出的 exceptions 一定只會是 FirstException 或 SecondException. 即使在 catch 條文中的 exception 參數 e 的型別是 Exception, 編譯器可以也判定它是 FirstException 或 SecondException 的實體.

 public void rethrowException (String exceptionName) throws FirstException, SecondException {
  try {
   // ...
  }
  catch (Exception e) {
   throw e;
  }
 }

This analysis is disabled if the catch parameter is assigned to another value in the catch block. However, if the catch parameter is assigned to another value, you must specify the exception type Exception in the throws clause of the method declaration.
如果在 catch 區塊中接收到的參數是被指派了其他型別的值, 那這個分析是不完整的. 總之, 如果有其他型別的參數會被指派,  你必須把該 exception 的型別宣告在方法宣告的 throw 條文之中.

In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions:
就細部而言, 在 Java SE 7 及其以後版本, 當你在 catch 條文中宣告一個或一個以上的 exception 型別, 而且 rethrow 在這個 catch 區塊中要處理的 exception  , 編譯器會滿足下列條件來查核被宣告丟出的 exception 的型別:

  • The try block is able to throw it.
    這個 try 區塊有能力丟出它.
  • There are no other preceding catch blocks that can handle it.
    之前沒有其他的 catch 區塊可以處理它.
  • It is a subtype or supertype of one of the catch clause's exception parameters.
    它是 catch 條文中的  exception 參數中的其中一個參數的下層型別或上層型別.

The Java SE 7 compiler allows you to specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration because you can rethrow an exception that is a supertype of any of the types declared in the throws.
Java SE 7 編譯器允許你可以指定 exception 型別 FirstException 及 SecondException 在 rethrowException 方法宣告的 throws 條文中, 因為你可能 rethrow 的 exception 的型別, 會是在 throws 宣告的型別中的任何一個型別的上層型別.

In releases prior to Java SE 7, you cannot throw an exception that is a supertype of one of the catch clause's exception parameters. A compiler from a release prior to Java SE 7 generates the error, "unreported exception Exception; must be caught or declared to be thrown" at the statement throw e. The compiler checks if the type of the exception thrown is assignable to any of the types declared in the throws clause of the rethrowException method declaration. However, the type of the catch parameter e is Exception, which is a supertype, not a subtype, of FirstException and SecondException.
在 Java SE  7 之前釋出的版出, 你不可以丟出 throws 條文中宣告的 exception 參數的上層型別的 exception. Java SE 7 之前版本的編譯器會針對 throw e 這行敘述, 產生一個 error: "unreported exception Exception; must be caught or declared to be thrown". 之前版本的編譯器會依照宣告在 rethrowException 方法的 throws 條文中的型別來查核被丟出的物件是否是可指派的. 然而在 catch 區塊衵的參數 e 的型別是 Exception, 它是 FirstException 及 SecondException 的上層型別不是下層型別.

沒有留言:

張貼留言