上期回顾: 【Java笔记】第13章:集合
个人主页:C_GUIQU
归属专栏:Java
目录
正文
1. 异常的概念
异常是指程序运行过程中出现的非正常情况。当异常出现时,程序会执行一段预先准备好的代码来进行处理,这种处理有助于减少用户的损失,并为用户提供提示信息。
2. 异常的分类
Java 中的所有错误或异常都继承自 Throwable
类,位于 java.lang
包中。
2.1 Throwable
Throwable
类是 Java 中所有异常和错误的父类,包含以下常用方法:
String getMessage()
:获取字符串类型的异常信息,用于向用户展示提示。void printStackTrace()
:输出详细的异常信息,用于编程人员调试。
2.2 Error
Error
类是 Throwable
的子类,代表程序无法自行恢复的严重错误,例如 JVM 内存不足或栈溢出。通常情况下,这类错误不应该通过程序代码进行捕获和处理。
例子:栈溢出错误
public class StackOverflowExample {
public void recursiveMethod() {
recursiveMethod(); // 递归调用导致栈溢出
}
public static void main(String[] args) {
new StackOverflowExample().recursiveMethod();
}
}
2.3 Exception
Exception
类也是 Throwable
的子类,代表可以通过代码处理的异常。分为以下两类:
2.3.1 RuntimeException(运行时异常)
这类异常在编译时不会被检测,但可能在运行时出现,例如:
java.lang.ArrayIndexOutOfBoundsException
:数组下标越界java.lang.NullPointerException
:空指针异常java.lang.ClassCastException
:类型转换异常java.lang.NumberFormatException
:数字格式转换异常
例子:空指针异常
public class NullPointerExample {
public static void main(String[] args) {
String str = null;
System.out.println(str.length()); // 会引发 NullPointerException
}
}
2.3.2 非RuntimeException(已检查异常)
这类异常在编译时必须被处理,例如 Class.forName()
可能抛出的异常。
例子:已检查异常
public class CheckedExceptionExample {
public static void main(String[] args) {
try {
Class.forName("com.example.NonExistentClass");
} catch (ClassNotFoundException e) {
e.printStackTrace(); // 捕获并处理异常
}
}
}
3. 异常的产生
3.1 自动产生异常
程序在运行过程中,遇到错误代码会自动产生异常,一旦出现异常,程序会被终止,无法继续执行后续代码。
3.2 手动产生异常
使用 throw
关键字可以在代码中手动产生异常,用于在特定条件下结束程序的执行。
public class ThrowExample {
public static void main(String[] args) {
int age = -5;
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
}
}
4. 异常的传递
Java 中的异常沿着方法的调用链进行反方向传递,最终传递给 JVM,导致程序终止。
5. 异常的处理
5.1 消极处理异常(声明异常)
使用 throws
关键字在方法声明中消极处理异常,推卸异常处理的责任,但程序依然会因异常而终止。
public void riskyMethod() throws IOException {
// 方法可能抛出 IOException
}
5.2 积极处理异常(捕获异常)
使用 try-catch
结构捕获和处理异常。
public class TryCatchExample {
public static void main(String[] args) {
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[5]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界:" + e.getMessage());
} finally {
System.out.println("无论是否发生异常,都会执行");
}
}
}
注意
try
后可以跟多个catch
,用于捕获不同类型的异常。catch
中可以使用父类型异常来处理子类异常。
6. 自定义异常
通过继承 Exception
类或其子类,可以创建自定义异常。如果继承 RuntimeException
,则抛出的异常为运行时异常。
例子:自定义异常
public class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
public CustomException() {
super("自定义异常");
}
}
public class CustomExceptionTest {
public static void main(String[] args) {
try {
throw new CustomException("这是一个自定义异常");
} catch (CustomException e) {
e.printStackTrace();
}
}
}
7. 方法覆盖中的异常处理
在方法覆盖(重写)时,子类的方法不能抛出比父类更多或更宽的异常。
例子:方法覆盖中的异常限制**
class Parent {
public void doSomething() throws IOException {
// 父类方法抛出 IOException
}
}
class Child extends Parent {
@Override
public void doSomething() throws FileNotFoundException {
// 子类可以抛出与父类相同或更具体的异常
}
}
8. 知识拓展
- 异常捕获的最佳实践:建议尽量使用具体的异常类型进行捕获,而不是使用通用的
Exception
类。这样可以使代码更加明确,便于维护。 finally
的应用场景:finally
块通常用于释放资源,如关闭文件流、数据库连接等,确保资源不会因为异常的发生而无法关闭。- 异常链:可以使用
Throwable.initCause(Throwable)
方法将一个异常作为另一个异常的原因,从而形成异常链,以便于更好地追踪异常的来源。
结语
感谢您的阅读!期待您的一键三连!欢迎指正!