2012-09-25 31 views
0

我試圖理解爲什麼要使用異常。 想,如果我有一個計劃,什麼時候應該在java中使用例外

(不使用的try/catch)

public class ExceptionExample { 

private static String str; 

public static void main(String[] args) { 
    System.out.println(str.length()); 
} 

我得到異常

Exception in thread "main" java.lang.NullPointerException 
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:22) 

現在使用的try/catch,

public class ExceptionExample { 

private static String str; 

public static void main(String[] args) { 
    try { 
     System.out.println(str.length()); 
    } catch(NullPointerException npe) { 
     npe.printStackTrace(); 
    } 
} 

}

我有例外,

java.lang.NullPointerException 
at com.Hello.ExceptionExample.ExceptionExample.main(ExceptionExample.java:9) 

現在的問題是,

在這兩種情況下我有印刷相同的消息。那麼使用try/catch有什麼用處?和

捕捉異常後我們能做些什麼,在這種情況下我已經打印了堆棧跟蹤。捕獲僅用於打印跟蹤還是使用getMessage()或getClass()查找異常詳細信息?

+1

未捕獲的異常會導致應用程序異常終止,因此最好儘可能使用異常處理機制來捕獲和處理異常,以防止有時會導致系統崩潰的意外問題/行爲。 – Lion

+0

http://docs.oracle.com/javase/tutorial/essential/exceptions/ – Natix

回答

5

實際上,這個區別非常大。

佔據第一位,並在打印之後添加一行:

public class ExceptionExample { 

    private static String str; 

    public static void main(String[] args) { 
     System.out.println(str.length()); 
     System.out.println("Does this execute?"); 
    } 
} 

你會看到Does this execute?不打印因爲異常中斷碼流並停止它時,它是不抓住。

在另一方面:

public class ExceptionExample { 

    private static String str; 

    public static void main(String[] args) { 
     try { 
      System.out.println(str.length()); 
     } catch(NullPointerException npe) { 
      npe.printStackTrace(); 
     } 
     System.out.println("Does this execute?"); 
    } 
} 

將打印兩個堆棧跟蹤Does this execute?。這是因爲捕捉異常就像說:「我們將在這裏處理並繼續執行。」

另一種說法是,catch塊是應該發生錯誤恢復的地方,所以如果發生錯誤但我們可以從中恢復,我們會將恢復代碼放在那裏。

編輯:

這裏的一些錯誤恢復的一個例子。假設我們有一個不存在的文件C:\nonexistentfile.txt。我們想嘗試打開它,如果我們找不到它,請向用戶顯示一條消息,指出它已丟失。這可以通過捕捉在這裏產生的FileNotFoundException來完成:

// Here, we declare "throws IOException" to say someone else needs to handle it 
// In this particular case, IOException will only be thrown if an error occurs while reading the file 
public static void printFileToConsole() throws IOException { 
    File nonExistent = new File("C:/nonexistentfile.txt"); 
    Scanner scanner = null; 
    try { 
     Scanner scanner = new Scanner(nonExistent); 
     while (scanner.hasNextLine()) { 
      System.out.println(scanner.nextLine()); 
     } 
    } catch (FileNotFoundException ex) { 
     // The file wasn't found, show the user a message 
     // Note use of "err" instead of "out", this is the error output 
     System.err.println("File not found: " + nonExistent); 
     // Here, we could recover by creating the file, for example 
    } finally { 
     if (scanner != null) { 
      scanner.close(); 
     } 
    } 
} 

因此,有幾件事情,這裏要注意:

  1. 我們趕上FileNotFoundException和使用自定義錯誤消息,而不是打印的堆棧跟蹤。我們的錯誤信息比打印堆棧跟蹤更清潔,更方便用戶使用。在GUI應用程序中,控制檯甚至可能對用戶不可見,所以這可能是代碼來向用戶顯示錯誤對話框。僅僅因爲文件不存在並不意味着我們不得不停止執行我們的代碼。
  2. 我們在方法簽名中聲明throws IOException,而不是將其與FileNotFoundException並行捕獲。在這種情況下,如果我們無法讀取文件(即使文件存在),則會在此處拋出IOException。對於這種方法,我們說在處理讀取文件時遇到的錯誤不是我們的責任。這是一個如何聲明不可恢復的錯誤的例子(不可恢復的,我的意思是在這裏不可恢復,它可能在更高的地方可以恢復,例如在名爲printFileToConsole的方法中)。
  3. 我不小心在這裏介紹finally塊,所以我會解釋它的作用。它保證,如果打開Scanner並在我們讀取文件時發生錯誤,則Scanner將被關閉。這很重要,原因很多,最值得注意的是,如果不關閉它,Java仍然會對文件鎖定,所以如果不退出應用程序就不能再次打開文件。
+0

「catch塊是應該發生錯誤恢復的地方,所以如果發生錯誤但我們可以從中恢復,我們會將恢復代碼放在那裏。」你能舉個例子嗎? – Amarnath

+0

@Che我更新了我的答案。 – Brian

0

如果使用異常,不要

catch(NullPointerException npe) { 
    npe.printStackTrace(); 
} 

簡單

catch(NullPointerException npe) { 
     //error handling code 
    } 

您是護身符刪除錯誤打印。而且不管怎麼說,一般的例外不僅僅是特定的。

+0

嗯...這是相反的方式。你應該抓住特定的,而不是一般的例外。看一些[更多細節](http://www.javaworld.com/javaworld/javatips/jw-javatip134.html)。你應該做的是,你應該抓住你能做到的最具體的例外。 – eis

+0

是的,但在頂部捕獲一般異常,如果任何已被傳遞未捕獲,所以我們(我是一個PHP程序員)使用繼承的異常類來捕獲特定的,然後使用全球嘗試捕獲處理任何未捕獲的異常 – geekman

+0

這取決於關於軟件的風格,我不認爲可以說一般應該做什麼。對於某些軟件,是的,我認爲可以這樣做,但絕對不是。 – eis

3

有兩種情況時,你應該拋出一個異常:當你發現不正確使用你的類(即一個編程錯誤)錯誤

  • 選中異常的實例,即的RuntimeException
  • 當檢測到被非編程錯誤以外的原因造成的錯誤(無效數據,丟失網絡連接,等等)拋出的Exception實例並不子類的子類RuntimeException

您應該捕獲第二種異常,而不是第一種異常。此外,如果您的計劃採取措施糾正異常情況,則應該檢查異常情況;例如,如果您檢測到連接丟失,則您的程序可能會讓用戶重新連接到網絡並重試該操作。在代碼無法充分處理異常的情況下,讓它傳播到可以處理它的圖層。

1

try/catch將會阻止你的應用程序崩潰或確切地說 - 如果遇到無意的情況,執行不會停止。你可以把你的「有風險」的代碼包裝在try塊和catch塊中,你可以處理這個異常。通過處理,它意味着對這種情況做些事情並繼續執行。 如果沒有嘗試/捕獲,則在執行錯誤時停止執行,並且之後的任何代碼都不會執行。

就你而言,你可能已經打印出「這不是我所期望的,無論如何,讓我們繼續前進!」

1

假設您已連接到數據庫,但在讀取記錄時會引發一些異常。現在在這種情況下,您可以關閉Finally塊中的連接。你只是在這裏避免了內存泄漏。 我的意思是,即使通過捕獲和處理異常,您也可以執行任務。

1

在你給出的例子中,你是對的,沒有任何好處。

您應該只捕獲異常如果任

  • 你可以做一些事情(報告,添加信息,修復的情況下),或
  • 你必須這樣做,因爲檢查異常強迫你

通常情況下,「處理」異常會將情況記錄到您選擇的日誌文件中,添加任何相關的上下文相關信息並讓流程繼續。添加上下文信息對解決問題有很大的好處。所以,在你的榜樣,你可能會尋找一個這樣的消息時完成

public static void main(String[] args) { 
    try { 
     System.out.println(str.length()); 
    } catch(NullPointerException npe) { 
     System.err.println(
      "Tried looking up str.length from internal str variable," 
       +" but we got an exception with message: " 
       + npe.getMessage()); 
     npe.printStackTrace(System.err); 
    } 
} 

,有人會知道基於什麼地方出了錯,甚至可以採取何種解決它的消息。

0

如果你看看兩個例外,它們實際上是不同的。第一個引用第22行,而第二個引用第9行。這聽起來像添加try/catch捕獲第一個異常,但另一行代碼也引發異常。

因此,拋出異常是因爲您從未創建過新的字符串,或者爲該字符串設置了值,除非它是在未顯示的代碼的一部分中完成的。

添加一個try/catch塊對於你幾乎不能控制的對象是非常有用的,所以如果這些對象不是預期的(比如null),你可以正確處理這個問題。

字符串通常是您首先要實例化的東西,所以您通常不必擔心使用try/catch。

希望這會有所幫助。

0

要回答您原來的問題車,「何時使用異常?」

在Java中 - 我相信你已經發現了...... Java中有某些方法需要try/catch。這些方法「拋出」例外,並且意味着。沒有其他辦法了。

例如,

FileUtils.readFileToString(new File("myfile.txt")); 

不會讓你編譯直到你加入try/catch語句。

另一方面,例外是非常有用的,因爲你可以從中得到什麼。

以Java反射例如...

try { Class.forName("MyClass").getConstructor().newInstance(); } 
catch (ClassNotFoundException x) { // oh it doesnt exist.. do something else with it. 

所以完全回答你的問題 -

使用的try/catch謹慎,因爲它是典型的「不贊成」,在您的應用程序的處置錯誤。 。相反,當你的方法需要它們時使用它們。

相關問題