學習軌道
/
Java
Java
/
練習
/
計算機難題
計算機難題

計算機難題

學習練習

簡介

例外

Java 程式語言使用_例外_來處理錯誤和其他異常事件。

什麼是例外

例外是在程式執行期間發生、會打斷指令正常流程的事件。 在 Java 中,例外是明確地被拋出的,而拋出例外的動作稱為_拋出例外_。 處理例外的動作則稱為_捕捉例外_。

在 Java 中,所有例外都是Exception類別的子類別,而Exception本身又是Throwable的子類別。

Java 將例外區分為 2 種:

  1. 受檢例外
  2. 未受檢例外
受檢例外

_受檢例外_是應用程式應該預期,並能從中復原的異常狀況。 受檢例外的一個例子是FileNotFoundException,當方法試圖讀取不存在的檔案時就會發生。

這類例外會在編譯期受到檢查:拋出受檢例外的方法必須在方法簽章中註明,而呼叫可能拋出受檢例外的方法的程式碼則必須處理它,否則程式碼無法編譯。

所有受檢例外都是Exception的子類別,且不繼承RuntimeException。

未受檢例外

_未受檢例外_是應用程式通常無法預期、也無法從中復原的異常狀況。 未受檢例外的一個例子是NullPointerException,當方法預期收到非 null 的值,卻收到null時就會發生。

這類例外不會在編譯期受到檢查:拋出未受檢例外的方法不必在方法簽章中註明,而呼叫可能拋出未受檢例外的方法的程式碼也不一定要處理它。

所有未受檢例外都繼承自RuntimeException,而RuntimeException本身則是Exception的延伸。

拋出例外

Java 中的方法可以使用throw敘述來拋出例外。

拋出受檢例外

從方法拋出受檢例外時,必須使用throws關鍵字在方法簽章中註明,如下方範例所示。 這會強制呼叫端的程式碼預期例外可能被拋出,並據此處理。

public class InsufficientBalanceException extends Exception {

}

public class BankAccount {
  public void withdraw(double amount) throws InsufficientBalanceException {
    if (balance < amount) {
      throw new InsufficientBalanceException();
    }

    // rest of the method implementation
  }
}
拋出未受檢例外

從方法拋出未受檢例外時,不一定要在方法簽章中註明,雖然 Java 也支援這樣做。

public class BankAccount {
  public void withdraw(double amount) {
    if (amount < 0) {
      throw new IllegalArgumentException("Cannot withdraw a negative amount");
    }

    // rest of the method implementation
  }
}

處理例外

在 Java 中,處理例外是透過try、catch和finally關鍵字來完成。

  • 可能拋出例外的程式敘述應該包在try區塊中。
  • try區塊後面接著一個或多個catch區塊,用來捕捉try區塊中拋出的例外。
  • catch區塊後面可以選擇性地加上finally區塊,它會在try區塊之後一律執行,無論是否拋出例外。

以下範例示範這些關鍵字如何運作:

public class ATM {
  public void withdraw(BankAccount bankAccount, double amount) {
    try {
      System.out.println("Withdrawing " + amount);
      bankAccount.withdraw(amount);
      System.out.println("Withdrawal succeeded");
    } catch (InsufficientBalanceException) {
      System.out.println("Withdrawal failed: insufficient balance");
    } catch (RuntimeException e) {
      System.out.println("Withdrawal failed: " + e.getMessage());
    } finally {
      System.out.println("Current balance: " + bankAccount.getBalance());
    }
  }
}

在這個範例中,沒有拋出例外時會印出以下內容:

Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0

不過,如果bankAccount.withdraw(amount)敘述拋出InsufficientBalanceException,就會印出以下內容:

Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0

或者,如果bankAccount.withdraw(amount)拋出未受檢例外,就會印出以下內容:

Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0

錯誤

Java 另外還有一個稱為_錯誤_的獨立類別,指的是應用程式外部的嚴重問題。 錯誤的一個例子是OutOfMemoryError,當應用程式試圖使用超過系統可用記憶體時就會發生。

和未受檢例外一樣,錯誤不會在編譯期受到檢查。 差別在於,它們代表系統層級的問題,通常是由 Java 虛擬機器或環境拋出,而不是應用程式。 應用程式通常不應該嘗試捕捉或處理它們。

Java 中的所有錯誤都繼承自Error類別。

說明

在這個練習中,你將為一個簡單的整數計算機建立錯誤處理。 為了讓事情單純一些,我們已經提供了計算加法、乘法和除法的方法。

目標是做出一個能正常運作的計算機,當傳入引數 16、51 和 + 時,它會回傳符合以下模式的字串:16 + 51 = 67。

CalculatorConundrum calculator = new CalculatorConundrum();

calculator.calculate(16, 51, "+");
// => returns "16 + 51 = 67"

calculator.calculate(32, 6, "*");
// => returns "32 * 6 = 192"

calculator.calculate(512, 4, "/");
// => returns "512 / 4 = 128"

1. 實作 calculate 方法以支援幾種基本運算

這個任務中主要要實作的方法是 CalculatorConundrum.calculate() 方法。 它接受三個引數。 前兩個引數 operand1 和 operand2 是要進行運算的整數。 第三個引數 operation 的型別是字串,而在這個練習中,必須實作以下運算:

  • 使用 + 字串的加法
  • 使用 * 字串的乘法
  • 使用 / 字串的除法

2. 處理不合法的運算

更新 CalculatorConundrum.calculate() 方法,以處理不合法的運算:

  • 當 operation 引數是 null 時,應該拋出 IllegalArgumentException,訊息為 Operation cannot be null。
  • 當 operation 引數是 "" 時,應該拋出 IllegalArgumentException,訊息為 Operation cannot be empty。
  • 當 operation 引數是 +、* 或 / 以外的任何運算時,應該拋出 IllegalOperationException,訊息為 Operation '{operation}' does not exist。
calculator.calculate(10, 1, null);
// => throws IllegalArgumentException with message "Operation cannot be null"

calculator.calculate(10, 1, "");
// => throws IllegalArgumentException with message "Operation cannot be empty"

calculator.calculate(10, 1, "-");
// => throws IllegalOperationException with message "Operation '-' does not exist"

3. 處理除以零時拋出的例外

在 Java 中,嘗試除以零會拋出 ArithmeticException。 更新 CalculatorConundrum.calculate() 方法來攔截這個例外,然後拋出 IllegalOperationException,訊息為 Division by zero is not allowed,並以攔截到的 ArithmeticException 作為它的原因。

calculator.calculate(512, 0, "/");
// => throws IllegalOperationException with message "Division by zero is not allowed"
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Java Exercism

準備好開始 計算機難題 了嗎?

註冊 Exercism,透過 26 個概念158 個練習 和真人引導來學習並精通 Java,全部免費。