Java异常处理全解析
在Java编程中,异常处理是保证程序稳定性和健壮性的重要手段。本文将详细介绍Java中的异常处理机制,包括异常类型、处理方式以及相关的代码示例。
1. 异常处理基础编码任务
在Java编程中,为了避免程序因异常而崩溃,我们需要使用
try-catch
语句来捕获和处理异常。以下是一些具体的编码任务及解决方案。
1.1 添加
try-catch
语句避免代码崩溃
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
String[] words = new String[5];
int i = 0;
try {
do {
words[i] = keyboard.next();
} while (!words[i++].equals("Quit"));
for (int j = 0; j < 5; j++) {
System.out.println(words[j].length());
}
} catch (Exception e) {
System.out.println("An error occurred: " + e.getMessage());
} finally {
keyboard.close();
}
}
}
上述代码添加了
try-catch
语句,当输入出现异常时,程序会捕获异常并输出错误信息,同时在
finally
块中关闭
Scanner
对象,确保资源被正确释放。
1.2 改进代码处理用户输入异常
在某些代码中,如涉及用户输入价格和箱子数量的情况,为了避免输入不合法的值(如负数)导致程序出错,我们可以使用
try-catch
语句来处理。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double price = 0;
int boxCount = 0;
try {
System.out.print("Enter the price of each box: ");
price = scanner.nextDouble();
if (price < 0) {
throw new IllegalArgumentException("Price cannot be negative.");
}
System.out.print("Enter the number of boxes: ");
boxCount = scanner.nextInt();
if (boxCount < 0) {
throw new IllegalArgumentException("Number of boxes cannot be negative.");
}
// 处理合法输入
System.out.println("Price: " + price + ", Box count: " + boxCount);
} catch (IllegalArgumentException e) {
System.out.println("Invalid input: " + e.getMessage());
} catch (Exception e) {
System.out.println("An error occurred: " + e.getMessage());
} finally {
scanner.close();
}
}
}
此代码通过
try-catch
语句捕获用户输入的异常,当输入为负数时,会抛出
IllegalArgumentException
并进行相应处理。
2. 处理
InterruptedException
异常
在Java中,
Thread.sleep
方法可以让程序暂停执行一段时间,但该方法可能会抛出
InterruptedException
异常,这是一种受检查异常,需要在代码中进行处理。
2.1 错误示例
import static java.lang.System.out;
public class NoSleepForTheWeary {
public static void main(String args[]) {
out.print("Excuse me while I nap ");
out.println("for just five seconds...");
takeANap();
out.println("Ah, that was refreshing.");
}
static void takeANap() {
Thread.sleep(5000);
}
}
上述代码编译时会报错,因为
Thread.sleep
方法可能抛出
InterruptedException
异常,但没有在代码中进行处理。
2.2 使用
try-catch
语句处理异常
import static java.lang.System.out;
public class GoodNightsSleepA {
public static void main(String args[]) {
out.print("Excuse me while I nap ");
out.println("for just five seconds...");
takeANap();
out.println("Ah, that was refreshing.");
}
static void takeANap() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
out.println("Hey, who woke me up?");
}
}
}
在这个示例中,
takeANap
方法使用
try-catch
语句捕获
InterruptedException
异常,当异常发生时,会输出相应的提示信息。
2.3 使用
throws
子句传递异常
import static java.lang.System.out;
public class GoodNightsSleepB {
public static void main(String args[]) {
out.print("Excuse me while I nap ");
out.println("for just five seconds...");
try {
takeANap();
} catch (InterruptedException e) {
out.println("Hey, who woke me up?");
}
out.println("Ah, that was refreshing.");
}
static void takeANap() throws InterruptedException {
Thread.sleep(5000);
}
}
此示例中,
takeANap
方法使用
throws
子句声明可能抛出
InterruptedException
异常,将异常处理的责任传递给调用该方法的
main
方法,
main
方法使用
try-catch
语句进行处理。
3. Java异常类型
Java中的异常分为受检查异常(Checked Exceptions)和非受检查异常(Unchecked Exceptions)。
| 异常类型 | 说明 | 示例 |
|---|---|---|
| 受检查异常 | 必须在代码中进行处理,否则编译不通过 |
InterruptedException
、
IOException
、
SQLException
|
| 非受检查异常 | 不需要在代码中显式处理 |
NumberFormatException
、
ArithmeticException
、
IndexOutOfBoundsException
、
NullPointerException
|
4. 异常处理流程
graph TD;
A[开始执行代码] --> B{是否抛出异常};
B -- 是 --> C{是否在try块内};
C -- 是 --> D{是否有匹配的catch块};
D -- 是 --> E[执行catch块代码];
D -- 否 --> F[跳出当前方法,返回调用处];
C -- 否 --> F;
B -- 否 --> G[继续执行后续代码];
E --> H{是否有finally块};
H -- 是 --> I[执行finally块代码];
H -- 否 --> G;
I --> G;
通过以上内容,我们了解了Java中异常处理的基本概念、不同类型的异常以及如何使用
try-catch
语句和
throws
子句处理异常,同时也掌握了异常处理的流程。在实际编程中,合理运用异常处理机制可以提高程序的稳定性和健壮性。
Java异常处理全解析
5. 修复未处理的异常
在实际编程中,我们经常会遇到代码因未处理异常而无法编译的情况,下面将针对具体示例进行修复。
5.1 修复
FileNotFoundException
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner diskScanner = null;
try {
diskScanner = new Scanner(new File("numbers.txt"));
int[] numerators = new int[5];
int[] denominators = new int[5];
int i = 0;
while (diskScanner.hasNextInt()) {
numerators[i] = diskScanner.nextInt();
denominators[i] = diskScanner.nextInt();
i++;
}
for (int j = 0; j < numerators.length; j++) {
try {
System.out.println(numerators[j] / denominators[j]);
} catch (ArithmeticException e) {
System.out.println("Division by zero occurred at index " + j);
}
}
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} finally {
if (diskScanner != null) {
diskScanner.close();
}
}
}
}
上述代码首先添加了
try-catch
语句来捕获
FileNotFoundException
,确保代码能够编译。同时,在进行除法运算时,又添加了
try-catch
语句来捕获可能出现的
ArithmeticException
,避免程序因除零错误而崩溃。
5.2 修复其他异常
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
File fileIn = new File("input");
File fileOut = new File("output");
try (FileInputStream fileInStrm = new FileInputStream(fileIn);
DataInputStream dataInStrm = new DataInputStream(fileInStrm);
FileOutputStream fileOutStrm = new FileOutputStream(fileOut);
DataOutputStream dataOutStrm = new DataOutputStream(fileOutStrm)) {
int numFilesCopied = 0;
try {
while (true) {
dataOutStrm.writeByte(dataInStrm.readByte());
}
} catch (EOFException e) {
numFilesCopied = 1;
}
} catch (IOException e) {
System.out.println("An I/O error occurred: " + e.getMessage());
}
}
}
此代码使用了
try-with-resources
语句来自动关闭资源,避免了手动关闭资源可能出现的问题。同时,捕获了
IOException
,处理文件读写过程中可能出现的异常。
6. 使用
finally
子句
finally
子句的作用是无论是否抛出异常,其中的代码都会被执行。以下是一个示例:
import static java.lang.System.out;
public class DemoFinally {
public static void main(String args[]) {
try {
doSomething();
} catch (Exception e) {
out.println("Exception caught in main.");
}
}
static void doSomething() {
try {
out.println(0 / 0);
} catch (Exception e) {
out.println("Exception caught in doSomething.");
out.println(0 / 0);
} finally {
out.println("I'll get printed.");
}
out.println("I won't get printed.");
}
}
在这个示例中,
finally
子句中的代码
out.println("I'll get printed.");
无论是否抛出异常都会被执行。而在
catch
块中再次抛出异常后,
out.println("I won't get printed.");
不会被执行。
7.
try-with-resources
语句
当程序使用多个资源时,使用
try-with-resources
语句可以更方便地管理资源,确保资源被正确关闭。
7.1 传统方式的问题
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner scan1 = null;
Scanner scan2 = null;
try {
scan1 = new Scanner(new File("File1.txt"));
scan2 = new Scanner(new File("File2.txt"));
// Do useful stuff
} catch (IOException e) {
// Oops!
} finally {
if (scan1 != null) {
scan1.close();
}
if (scan2 != null) {
scan2.close();
}
System.out.println("Done!");
}
}
}
传统方式中,如果在
try
块中提前关闭了某个资源,可能会导致
finally
块中关闭资源时出现
NullPointerException
。
7.2 使用
try-with-resources
语句
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class NewMain {
public static void main(String args[]) {
try (Scanner scan1 = new Scanner(new File("File1.txt"));
Scanner scan2 = new Scanner(new File("File2.txt"))) {
// Do useful stuff
} catch (IOException e) {
// Oops!
}
System.out.println("Done!");
}
}
使用
try-with-resources
语句,Java会自动关闭声明在括号内的资源,避免了手动关闭资源可能出现的问题。
8. 总结
通过以上内容,我们深入了解了Java异常处理的各个方面,包括异常类型、处理方式以及资源管理。以下是对重要知识点的总结:
-
异常类型
:分为受检查异常和非受检查异常,受检查异常必须在代码中处理,非受检查异常可以不处理。
-
异常处理方式
:可以使用
try-catch
语句捕获并处理异常,也可以使用
throws
子句将异常传递给调用者。
-
finally
子句
:无论是否抛出异常,
finally
子句中的代码都会被执行,常用于释放资源。
-
try-with-resources
语句
:用于管理多个资源,自动关闭声明在括号内的资源,避免手动关闭资源可能出现的问题。
在实际编程中,合理运用这些异常处理机制可以提高程序的稳定性和健壮性,减少因异常导致的程序崩溃。希望大家通过本文的学习,能够更好地掌握Java异常处理的技巧。
超级会员免费看

被折叠的 条评论
为什么被折叠?



