Java 學習記錄81 — Catching and throwing Exception

張小雄
4 min readSep 15, 2021

今天要學 Catching and throwing Exception

import java.util.InputMismatchException;
import java.util.Scanner;
public class CatchingAndThrowingExceptions {
public static void main(String[] args) {
int result = divide();
System.out.println("x / y = " + result);
}
private static int divide() {
int x = getInt();
int y = getInt();
System.out.println("x is " + x + ", y is " + y);
return x / y;
}
private static int getInt() {
Scanner s = new Scanner(System.in);
System.out.print("Please enter an integer: ");
while (true) {
try {
return s.nextInt();
} catch (InputMismatchException e) {
// go round again. Read past the end of line in the input first
s.nextLine();
System.out.println("Please enter a number using only the digits 0 to 9 ");
}
}
}
}

輸出結果:

Please enter an integer: 6

Please enter an integer: 3h3

Please enter a number using only the digits 0 to 9

Please enter a number using only the digits 0 to 9

..

Please enter a number using only the digits 0 to 9

1123

x is 6, y is 1123

x / y = 0

用 catch 捕捉了非數字輸入

但如果輸入 ctrl + d,因為不屬於 InputMismatchException 所以沒有捕捉到

輸出結果:

Please enter an integer: ^D

Exception in thread “main” java.util.NoSuchElementException

at java.base/java.util.Scanner.throwFor(Scanner.java:937)

at java.base/java.util.Scanner.next(Scanner.java:1594)

at java.base/java.util.Scanner.nextInt(Scanner.java:2258)

at java.base/java.util.Scanner.nextInt(Scanner.java:2212)

at CatchingAndThrowingExceptions.getInt(CatchingAndThrowingExceptions.java:22)

at CatchingAndThrowingExceptions.divide(CatchingAndThrowingExceptions.java:11)

at CatchingAndThrowingExceptions.main(CatchingAndThrowingExceptions.java:6)

拋出的是 NoSuchElementException

import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class CatchingAndThrowingExceptions {
public static void main(String[] args) {
int result = divide();
System.out.println("x / y = " + result);
}
private static int divide() {
int x;
try {
x = getInt();
} catch (NoSuchElementException e) {
x = getInt();
}
int y = getInt();
System.out.println("x is " + x + ", y is " + y);
return x / y;
}
private static int getInt() {
Scanner s = new Scanner(System.in);
System.out.print("Please enter an integer: ");
while (true) {
try {
return s.nextInt();
} catch (InputMismatchException e) {
// go round again. Read past the end of line in the input first
s.nextLine();
System.out.println("Please enter a number using only the digits 0 to 9 ");
}
}
}
}

輸出結果:

Please enter an integer: ^D

Please enter an integer: Exception in thread “main” java.util.NoSuchElementException

at java.base/java.util.Scanner.throwFor(Scanner.java:937)

at java.base/java.util.Scanner.next(Scanner.java:1594)

at java.base/java.util.Scanner.nextInt(Scanner.java:2258)

at java.base/java.util.Scanner.nextInt(Scanner.java:2212)

at CatchingAndThrowingExceptions.getInt(CatchingAndThrowingExceptions.java:28)

at CatchingAndThrowingExceptions.divide(CatchingAndThrowingExceptions.java:16)

at CatchingAndThrowingExceptions.main(CatchingAndThrowingExceptions.java:7)

為啥在 divide() catch 了 NoSuchElementException 還是報錯?

首先 try 裡的 getInt() 用戶輸入的 "^D" (ctrl + d)

被 catch NoSuchElementException 捕捉到了

進去執行裡面的代碼,又做了第二次 getInt()

因為 ctrl + d 代表中斷,所以第二次啥都沒讀到

此時這段已經沒有了 catch NoSuchElementException

就直接報錯了

Kirk

When Tim typed in <ctrl + d> “^D” a NoSuchElementException was still thrown and caused the program to crash and the stack trace was printed to output. This is because even though the first exception was caught another attempt was made to read an integer in the catch block which threw the same exception. The ^D character closed the input stream and so even though another attempt was made by the scanner to read an integer there was nothing to read and so another exception was thrown.

另外提醒一下,try 裡面的變量就只能在裡面用,外面是讀不到的

但在此函數最後要 return x,要用到 x,所以才會在函數內聲明 x

import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class CatchingAndThrowingExceptions {
public static void main(String[] args) {
int result = divide();
System.out.println("x / y = " + result);
}
private static int divide() {
int x, y;
try {
x = getInt();
y = getInt();
} catch (NoSuchElementException e) {
throw new NoSuchElementException("Fuck off! I need an Int");
}
System.out.println("x is " + x + ", y is " + y);
try {
return x / y;
} catch (ArithmeticException e) {
throw new ArithmeticException("Stupid! u can't divide by 0 ");
}
}
private static int getInt() {
Scanner s = new Scanner(System.in);
System.out.print("Please enter an integer: ");
while (true) {
try {
return s.nextInt();
} catch (InputMismatchException e) {
// go round again. Read past the end of line in the input first
s.nextLine();
System.out.println("Please enter a number using only the digits 0 to 9 ");
}
}
}
}

輸出結果:

Please enter an integer: ^D

Exception in thread “main” java.util.NoSuchElementException: Fuck off! I need an Int

at CatchingAndThrowingExceptions.divide(CatchingAndThrowingExceptions.java:17)

at CatchingAndThrowingExceptions.main(CatchingAndThrowingExceptions.java:7)

輸出結果:

Please enter an integer: 3

Please enter an integer: 0

x is 3, y is 0

Exception in thread “main” java.lang.ArithmeticException: Stupid! u can’t divide by 0

at CatchingAndThrowingExceptions.divide(CatchingAndThrowingExceptions.java:23)

at CatchingAndThrowingExceptions.main(CatchingAndThrowingExceptions.java:7)

throw 就是自己決定要拋出啥異常,而且連文字都可以改,很有趣

Tim老師說常用於 log 紀錄程序錯誤原因

import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class CatchingAndThrowingExceptions {
public static void main(String[] args) {
try {
int result = divide();
System.out.println("x / y = " + result);
} catch (ArithmeticException e) {
e.printStackTrace();
System.out.println("Unable to perform division, autopilot shutdown.");
}
}
private static int divide() {
int x, y;
try {
x = getInt();
y = getInt();
System.out.println("x is " + x + ", y is " + y);
return x / y;
} catch (NoSuchElementException e) {
throw new NoSuchElementException("Fuck off! I need an Int");
} catch (ArithmeticException e) {
throw new ArithmeticException("Stupid! u can't divide by 0 ");
}
}
private static int getInt() {
Scanner s = new Scanner(System.in);
System.out.print("Please enter an integer: ");
while (true) {
try {
return s.nextInt();
} catch (InputMismatchException e) {
// go round again. Read past the end of line in the input first
s.nextLine();
System.out.println("Please enter a number using only the digits 0 to 9 ");
}
}
}
}

輸出結果:

Please enter an integer: ^D

Exception in thread “main” java.util.NoSuchElementException: Fuck off! I need an Int

at CatchingAndThrowingExceptions.divide(CatchingAndThrowingExceptions.java:24)

at CatchingAndThrowingExceptions.main(CatchingAndThrowingExceptions.java:8)

稍微整理一下

import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class CatchingAndThrowingExceptions {
public static void main(String[] args) {
try {
int result = divide();
System.out.println(result);
} catch (ArithmeticException | NoSuchElementException e) {
System.out.println(e);
System.out.println("Unable to perform division, autopilot shutting down");
}
}
private static int divide() {
int x, y;
x = getInt();
y = getInt();
System.out.println("x is " + x + ", y is " + y);
return x / y;
}
private static int getInt() {
Scanner s = new Scanner(System.in);
System.out.println("Please enter an integer ");
while (true) {
try {
return s.nextInt();
} catch (InputMismatchException e) {
// go round again. Read past the end of line in the input first
s.nextLine();
System.out.println("Please enter a number using only the digits 0 to 9 ");
}
}
}
}

輸出結果:

Please enter an integer

^D

java.util.NoSuchElementException

Unable to perform division, autopilot shutting down

繼續整理,把 try 放到 main 裡,兩個 catch 合併成一個,這樣又更清楚了

本篇代碼

--

--