算术异常:
public class Test {
public static void main(String[] args) {
System.out.println(10/0);
}
}
数组越界异常 :
public class Test {
public static void main(String[] args) {
int[] array = {1,2,3};
System.out.println(array[100]);
}
}
空指针异常:
public class Test {
public static void main(String[] args) {
int[] array = null;
System.out.println(array.length);
}
}
以上列举的是我们写程序时常常遇见的三种异常爆红,为减少异常的发生,我们应该了解程序员的一生之敌,异常。
由图易知:所有异常均继承于Throwable,细分则为两个大的子类Error 和 Exception。
Error:系统级的错误和资源耗尽等严重问题。(一般不会遇见)
Error
,往往意味着程序无法继续正常运行,例如内存不足、栈溢出等。Error
中恢复,因为这些问题超出了程序的控制范围。Error
,因为处理这些问题通常超出了应用程序的能力。仅列举一个例子:
public class Test {
public class StackOverflowErrorExample {
public static void recursiveMethod() {
recursiveMethod();
}
}
public static void main(String[] args) {
StackOverflowErrorExample.recursiveMethod();
}
}
StackOverflowError
:当方法调用栈深度超过了 JVM 允许的最大深度时抛出,通常是由于递归调用没有正确的终止条件导致的。Exception:程序可以捕获和处理异常。
try-catch
块捕获并处理 Exception
,或者在方法签名中使用 throws
关键字声明抛出异常。Exception
中恢复,继续正常运行。try-catch块:这是最基础的异常处理方法
try{
//放置可能出现异常的代码
}catch(异常类型){
//处理异常代码
}catch(异常类型){
//处理异常代码
}...
try {
int[] arr = new int[5];
// 引发数组越界异常
arr[10] = 10;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("捕获到数组越界异常: " + e.getMessage());
} catch (Exception e) {
System.out.println("捕获到通用异常: " + e.getMessage());
}
同时借助getMessa方法可以获取详细的异常信息,便于调试和记录日志。
-
finally 块:和try-catch类型类似,只是在catch块后加入一个finally块。不管是否是否有异常抛出或者异常被处理,都会执行finally语句。该语句主要用于释放系统资源,关闭文件,资源库链接等。
try {
int num = 10 / 0; // 会抛出 ArithmeticException
} catch (ArithmeticException e) {
System.out.println("捕获到算术异常: " + e.getMessage());
} finally {
System.out.println("finally 块总是会被执行");
}
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class ThrowsExample {
// 声明该方法可能会抛出 IOException
public static void readFile() throws IOException {
File file = new File("nonexistent.txt");
FileReader reader = new FileReader(file);
}
public static void main(String[] args) {
try {
readFile();
} catch (IOException e) {
System.out.println("捕获到 I/O 异常: " + e.getMessage());
}
}
}
throw
关键字:手动抛出一个异常public class ThrowExample {
public static void checkAge(int age) {
if (age < 0) {
// 手动抛出 IllegalArgumentException
throw new IllegalArgumentException("年龄不能为负数");
}
System.out.println("年龄合法: " + age);
}
public static void main(String[] args) {
try {
checkAge(-5);
} catch (IllegalArgumentException e) {
System.out.println("捕获到异常: " + e.getMessage());
}
}
}
碰到一些特定的业务场景,这些场景下系统自带的异常类无法精准地描述问题。此时,你就可以自定义异常类来满足特定需求。
自定义异常类需要继承 Exception
类(用于创建编译时异常)或者 RuntimeException
类(用于创建运行时异常)。
Exception
类,编译器会强制要求你处理这类异常。RuntimeException
类,编译器不会强制要求你处理这类异常。需要提供参数的构造方法或者不带参数
例如:
// 自定义编译时异常类
class CustomCheckedException extends Exception {
// 无参构造方法
public CustomCheckedException() {
super();
}
// 带消息参数的构造方法
public CustomCheckedException(String message) {
super(message);
}
}
// 测试类
public class CustomCheckedExceptionTest {
public static void main(String[] args) {
try {
// 调用可能抛出异常的方法
throwException();
} catch (CustomCheckedException e) {
System.out.println("捕获到自定义编译时异常: " + e.getMessage());
}
}
public static void throwException() throws CustomCheckedException {
// 抛出自定义编译时异常
throw new CustomCheckedException("这是一个自定义编译时异常");
}
}
结果:
在上述代码中,CustomCheckedException
类继承自 Exception
类,是一个编译时异常类。在 throwException
方法中抛出该异常,在 main
方法中捕获并处理。
UsernameExistsException
异常。InvalidAgeException
异常。自定义异常可以让你更精准地描述程序中出现的问题,提高代码的可读性和可维护性。通过继承 Exception
或 RuntimeException
类,并提供合适的构造方法。