文章目录
- 4.1 异常类型和错误 - 遇见你的小怪兽
- 4.1.1 基础知识
- 4.1.2 重点案例:文件读取处理
- 4.1.3 拓展案例 1:处理空指针异常
- 4.1.4 拓展案例 2:捕获多个异常
- 4.2 异常处理机制 - 穿上你的超级英雄斗篷
- 4.2.1 基础知识
- 4.2.2 重点案例:用户登录验证
- 4.2.3 拓展案例 1:处理多个异常
- 4.2.4 拓展案例 2:使用 finally 清理资源
- 4.3 自定义异常 - 创造你自己的小怪兽
- 4.3.1 基础知识
- 4.3.2 重点案例:用户年龄验证
- 4.3.3 拓展案例 1:账户余额不足
- 4.3.4 拓展案例 2:数据格式验证
4.1 异常类型和错误 - 遇见你的小怪兽
在 Java 世界的深处,有两种主要的问题可能会打乱你代码的步伐:异常(Exception)和错误(Error)。这就像是你在编程道路上会遇到的两种小怪兽。让我们先来了解一下它们,然后学习如何勇敢地面对它们。
4.1.1 基础知识
-
异常(Exception):异常是程序运行时发生的问题,它们可能会打断程序的正常流程。Java 把异常分为两大类:
- 检查型异常(Checked Exceptions):这些异常必须被显式地捕获或者通过方法签名声明抛出。它们通常是外部错误,比如文件未找到或者类未找到等,我们可以预见并提前处理这些异常。
- 非检查型异常(Unchecked Exceptions):包括运行时异常(
RuntimeException
)和错误(Error
)。运行时异常是编程错误,如空指针异常或数组越界。这些异常通常是可以避免的。
-
错误(Error):错误是指在正常程序控制范围之外的问题,通常是由 JVM 系统内部错误或资源耗尽错误(如
StackOverflowError
或OutOfMemoryError
)引起的。当发生错误时,Java 运行时环境(JRE)通常无法继续运行。
4.1.2 重点案例:文件读取处理
假设你正在编写一个程序来读取用户指定的文件,并打印其内容。这是一个典型的情景,可能会遇到 FileNotFoundException
,这是一个检查型异常。
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileReaderDemo {
public static void main(String[] args) {
try {
File file = new File("example.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
scanner.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred: File not found.");
e.printStackTrace();
}
}
}
4.1.3 拓展案例 1:处理空指针异常
空指针异常(NullPointerException
)是最常见的运行时异常之一,通常发生在试图调用或访问 null
对象的成员时。
public class NullPointerDemo {
public static void main(String[] args) {
try {
String text = null;
System.out.println(text.length());
} catch (NullPointerException e) {
System.out.println("Caught NullPointerException.");
}
}
}
4.1.4 拓展案例 2:捕获多个异常
在某些情况下,一个代码块可能会抛出多种类型的异常。Java 允许你在一个 catch
块中捕获多种类型的异常,这可以使代码更简洁。
import java.io.*;
import java.util.*;
public class MultiCatchDemo {
public static void main(String[] args) {
try {
File file = new File("example.txt");
Scanner scanner = new Scanner(file);
System.out.println(10 / 0); // 故意制造除以零的异常
} catch (ArithmeticException | FileNotFoundException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
通过这些案例,我们可以看到 Java 异常处理的力量,它不仅可以帮助我们优雅地处理潜在的问题,还能确保即使在遇到异常时,我们的程序也能保持稳定运行。记住,勇敢地面对这些小怪兽,使用 Java 提供的工具来保护你的代码不受它们的影响。
4.2 异常处理机制 - 穿上你的超级英雄斗篷
在 Java 的世界里,异常处理机制就像是给你的代码穿上了一件超级英雄斗篷。它不仅保护你的程序不受意外的干扰,还确保了程序的健壮性和可靠性。让我们深入了解这件斗篷的超能力吧!
4.2.1 基础知识
-
try-catch:
try
块让你尝试执行一段可能会抛出异常的代码。如果异常发生,catch
块会捕获这个异常,让你有机会处理它。 -
finally:无论是否发生异常,
finally
块中的代码都会执行。这是清理资源的理想场所,比如关闭文件流或数据库连接。 -
throw:你可以使用
throw
关键字抛出一个异常。这通常用于指示方法遇到了无法自己处理的情况。 -
throws:当你的方法可能会抛出一个检查型异常,但不打算在当前方法内处理它时,你可以在方法签名中使用
throws
关键字声明这个异常。
4.2.2 重点案例:用户登录验证
假设我们正在编写一个用户登录的功能,需要验证用户输入的用户名和密码。如果用户输入不正确,我们会抛出一个异常。
class AuthenticationException extends Exception {
public AuthenticationException(String message) {
super(message);
}
}
public class Login {
public void authenticate(String username, String password) throws AuthenticationException {
if (!"admin".equals(username) || !"password".equals(password)) {
throw new AuthenticationException("Invalid username or password");
}
System.out.println("User authenticated successfully");
}
public static void main(String[] args) {
Login login = new Login();
try {
login.authenticate("user", "1234");
} catch (AuthenticationException e) {
System.out.println(e.getMessage());
}
}
}
4.2.3 拓展案例 1:处理多个异常
在实际应用中,你可能需要处理多种类型的异常。Java 允许你在一个 try
块中捕获多个异常,并分别处理它们。
public class MultiExceptionHandling {
public static void main(String[] args) {
try {
int[] numbers = new int[1];
numbers[10] = 10; // 这会抛出 ArrayIndexOutOfBoundsException
System.out.println(10 / 0); // 这会抛出 ArithmeticException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Array index is out of bounds!");
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
}
}
}
4.2.4 拓展案例 2:使用 finally 清理资源
在处理文件或数据库连接时,确保资源最终被关闭是非常重要的。即使发生异常,finally
块也可以保证这一点。
import java.io.*;
public class FileReading {
public static void main(String[] args) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("example.txt"));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
line = reader.readLine();
}
} catch (IOException e) {
System.out.println("Error reading file.");
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
System.out.println("Error closing the file.");
}
}
}
}
通过这些案例,我们可以看到 Java 异常处理机制的强大之处。它不仅帮助你优雅地处理程序中的意外情况,还确保了资源的正确管理和释放。记住,掌握这些技巧,你的代码就穿上了超级英雄的斗篷,无惧任何挑战!
4.3 自定义异常 - 创造你自己的小怪兽
在 Java 的异常处理机制中,有时预定义的异常无法完全满足我们的需求。这时,Java 给了我们一个超能力——创造自己的异常。这就像是在你的代码世界中创造一个全新的小怪兽,完全按照你的规则行动。
4.3.1 基础知识
要创建一个自定义异常,你只需要定义一个类继承自 Exception
类(对于检查型异常)或 RuntimeException
类(对于非检查型异常)。这个新类就是你的自定义异常,你可以添加任何你需要的属性或方法。
// 检查型异常示例
public class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
// 非检查型异常示例
public class MyUncheckedException extends RuntimeException {
public MyUncheckedException(String message) {
super(message);
}
}
4.3.2 重点案例:用户年龄验证
假设我们正在编写一个应用程序,需要验证用户的年龄是否满足特定条件。如果年龄不符合要求,我们将抛出一个自定义异常。
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
public class AgeValidator {
public void validateAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Age less than 18 is not allowed");
} else {
System.out.println("Age is valid");
}
}
public static void main(String[] args) {
AgeValidator validator = new AgeValidator();
try {
validator.validateAge(16);
} catch (InvalidAgeException e) {
System.out.println(e.getMessage());
}
}
}
4.3.3 拓展案例 1:账户余额不足
在一个银行应用程序中,当用户尝试提取超过其账户余额的金额时,我们可以抛出一个自定义异常来处理这种情况。
class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
public class BankAccount {
private double balance;
public BankAccount(double balance) {
this.balance = balance;
}
public void withdraw(double amount) throws InsufficientFundsException {
if (balance < amount) {
throw new InsufficientFundsException("Insufficient funds for withdrawal");
} else {
balance -= amount;
System.out.println("Withdrawal successful");
}
}
public static void main(String[] args) {
BankAccount account = new BankAccount(100);
try {
account.withdraw(150);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}
}
}
4.3.4 拓展案例 2:数据格式验证
在处理用户输入或文件读取时,我们可能需要验证数据的格式。如果数据格式不正确,抛出一个自定义异常是一个很好的做法。
class InvalidFormatException extends Exception {
public InvalidFormatException(String message) {
super(message);
}
}
public class DataProcessor {
public void processData(String data) throws InvalidFormatException {
if (!data.matches("\\d+")) { // 简单的数字格式验证
throw new InvalidFormatException("Data format is invalid");
} else {
System.out.println("Processing data: " + data);
}
}
public static void main(String[] args) {
DataProcessor processor = new DataProcessor();
try {
processor.processData("abc123");
} catch (InvalidFormatException e) {
System.out.println(e.getMessage());
}
}
}
通过这些案例,我们看到了自定义异常如何提高程序的可读性和健壮性。它们让异常处理变得更加具体和直观,帮助其他开发者(或未来的你)快速理解代码中可能发生的问题。创造你自己的小怪兽,让它们在需要时为你服务!