簡體   English   中英

異常-已檢查和未檢查的異常類型

[英]Exception - checked and unchecked exception type

我對java.lang.Exception及其在throw / throws子句中的考慮方式有疑問。

我有以下兩個示例,但我不完全了解java.lang.Exception是如何處理的:作為檢查還是未檢查的異常。

以下方法成功編譯:

public double method1() throws Exception {
   return 0.7;
}
  • 在我看來, java.lang.Exception受到威脅java.lang.RuntimeExceptionjava.lang.Error 即使您不處理它,也可以聲明將其拋出。
  • 如果不是使用Exception而是使用檢查的異常(屬於java.lang.Exception的子類),則您必須在方法的主體內具有throw聲明(或調用引發該檢查的異常的方法)。 對?

以下內容無法編譯:

private void method2(int age) {
   if (age > 30)
       throw new Exception();
}
  • 這是我的困惑...如果它拋出了本應編譯的java.lang.RuntimeExceptionjava.lang.Error類型的子類。
  • 為什么在這種情況下無法編譯? 我猜是因為它威脅java.lang.Exception作為已檢查的異常。 但是如果是這樣,那么method1為什么要編譯?

謝謝你,路易莎

如果它拋出java.lang.RuntimeException或java.lang.Error類型的子類,它將進行編譯嗎?

是的, RuntimeException是未經檢查的Exception(或Error ),因此您無需在方法簽名上聲明它或顯式catch它。 例如,類似於NullPointerException ,您無法確定在運行時代碼中何時會發生這種情況(即,由於哪個問題,因此,您無需在代碼內部的任何地方顯式處理它)。由於任何原因在運行時發生,您將看到異常stacktrace。

但是,有一點是,您可以catch (如果需要) RuntimeException (使用catch )並對其進行處理,如果您想在引發該異常時以不同的方式處理事情,則可以在下面進行查看。

try {
  //some code
} catch(ArithmeticException exe) {
   //handle it and you can do things differently how you like
}

同樣,該規則甚至也適用於throws ,即,如果您願意,您可以在方法簽名上指定throws ArithmeticException (或任何RuntimeException ),但是它對調用方沒有任何影響,而是會造成混亂代碼,但這不是最佳實踐,您可以在此處查看。 而當您在用於檢查的Exception的方法上指定throws Caluse時,則調用者被迫處理它,即,調用者方法必須使用catch塊顯式處理它或再次throw它。

為什么在這種情況下無法編譯? 我猜是因為它威脅java.lang.Exception作為已檢查的異常。 但是如果是這樣,那么method1為什么要編譯?

是的,有兩個規則可以處理檢查的異常:

(1) catch它的方法內使用catch

(2)或從方法中throw它(在方法簽名中使用throws

即,如果您的代碼塊throws了被檢查的throws ,那么您要么需要將其捕獲到方法內部,要么方法需要顯式聲明它拋出了Exception

在第一種方法1)中,

 public double method1() throws Exception { return 0.7; } 

您正在將異常 [即檢查異常]傳播到調用方法,這就是為什么您沒有看到編譯時異常的原因。 讓我向您展示一些可以使您更好地理解的東西,

  public void call() {
    method1(); // Because method1() is propagating compile time exception you must need to handle it here. 
  }

  public double method1() throws Exception  {
     return 0.7;
  }

在上面的代碼中,call()將獲得編譯時異常。

在第二種方法2)

private void method2(int age) {
   if (age > 30)
       throw new Exception(); //I am assuming you forgot to mention new in your code.
}

您將拋出檢查異常,因此您必須要處理它。 相反,如果將Exception()更改為RuntimeException,則在編譯時不會看到錯誤。 像下面一樣

private void method2(int age) {
       if (age > 30)
           throw new RuntimeException(); // you will not get compile time error.
    }

有關更多詳細信息,請訪問http://technostepup.com/CoreJava/ExceptionHandling/exception-types.php

在我看來,java.lang.Exception受到威脅java.lang.RuntimeException或java.lang.Error。 即使您不處理它,也可以聲明將其拋出。

如果不是使用Exception而是使用檢查的異常(屬於java.lang.Exception的子類),則您必須在方法的主體內具有throw聲明(或調用引發該檢查的異常的方法)。 對?

不可以。您可以聲明拋出任何異常(選中或未選中),並且不拋出任何異常。

例如,當方法在子類中被重寫並且您希望子類能夠引發檢查的異常時,這是有意義的。 重寫方法只能拋出父類聲明的檢查異常。

該方法需要像這樣進行編譯:

private void method2(int age) throws Exception
{
    if (age > 30)
        throw new Exception();
}

但是,檢查異常是一種能夠對該異常執行操作並執行有意義的操作(如釋放資源)的方式,只有當您拋出Exception的實際子類時,您才知道該異常的處理方法。

在method2中,您錯過了第一個new關鍵字

throw Exception();

在Java中,必須使用throws聲明聲明所有已檢查的異常,並且不能聲明未檢查的異常。

檢查的異常是從java.lang.Excetion類繼承的異常。 但是未經檢查的異常會繼承java.lang.RuntimeException類。

Throws子句用於聲明異常,thow關鍵字用於顯式拋出異常。 所以當你寫

private void method2(int age) {
    if (age > 30)
      throw Exception();
 }

您正在顯式引發一個異常,但沒有聲明該方法可以使用throws子句引發該異常。

所以正確的代碼將是

private void method2(int age) throws Exception {
if (age > 30)
    throw new Exception();
   }

在第一個示例中,如果調用該方法,則必須處理它引發的異常,因為它是已檢查的異常。 如果該方法引發了未經檢查的異常,則無需處理它。

您的第二個示例未編譯,因為您嘗試拋出Exception 您必須改為拋出它的一個實例。 如果出於同樣的原因,如果在該代碼中僅將Exception更改為RuntimeExceptionError或它們的子類,則仍然無法編譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM