嘿,刚踏入 Java 编程大门的小伙伴们!今天咱们来聊聊 Java 里超有意思的一个概念 —— 异常。别被这听起来高大上的名字唬住,其实它就像我们生活里各种突如其来的小意外,只不过发生在程序世界里。
想象一下,你写的 Java 程序是个超忙的外卖小哥,每天风风火火地执行各种任务,送餐(运行代码)、取餐(处理数据),一切都按计划进行。但突然有一天,外卖小哥遇到了麻烦:可能电动车没电了,或者顾客电话打不通,这些状况打乱了原本顺畅的送餐流程。在 Java 世界里,这些 “意外状况” 就叫做异常。
异常是什么?
简单来说,异常就是 Java 程序在运行过程中遇到的错误或不正常情况。当程序遇到异常时,如果不及时处理,就像外卖小哥遇到问题不解决,整个送餐流程就会 “瘫痪”,程序也会突然停止运行,还可能抛出一堆让你摸不着头脑的错误信息。
举个超级简单的例子,我们写个计算两个数相除的程序:
public class ExceptionExample {
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
int result = num1 / num2;
System.out.println("结果是:" + result);
}
}
运行这段代码,你会看到程序 “啪” 地一下报错了,抛出一个 ArithmeticException 异常,提示 “/by zero”,也就是除数不能为 0。这就好比外卖小哥遇到了 “路被封了,没法过去送餐” 的情况,程序没办法继续执行除法运算了。
异常的种类
在 Java 里,异常家族可庞大了,不过大致可以分为两类:受检异常(Checked Exception) 和 非受检异常(Unchecked Exception) 。
受检异常
受检异常就像你出门前必须检查的东西,比如钥匙、手机。Java 要求你必须在代码里显式处理这类异常,不然编译都通不过。常见的受检异常有 IOException(处理文件读写、网络连接等操作时可能遇到)、SQLException(操作数据库时可能出现)。
比如,我们尝试读取一个文件,如果文件不存在或者读取过程出问题,就会抛出 FileNotFoundException(它是 IOException 的子类):
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class CheckedExceptionExample {
public static void main(String[] args) {
try {
File file = new File("nonexistent.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("哎呀,文件找不到啦!");
e.printStackTrace();
}
}
}
这里我们用 try-catch 块把可能出现异常的代码包裹起来,如果真的抛出 FileNotFoundException,就会执行 catch 块里的代码,避免程序直接崩溃。
非受检异常
非受检异常就比较 “任性” 了,Java 不会强制你在编译时处理它。它们通常是由于代码逻辑错误导致的,比如前面提到的 ArithmeticException,还有 NullPointerException(访问空对象的方法或属性时会出现)、ArrayIndexOutOfBoundsException(数组下标越界)。
看个 NullPointerException 的例子:
public class UncheckedExceptionExample {
public static void main(String[] args) {
String str = null;
System.out.println(str.length());
}
}
运行这段代码,会抛出 NullPointerException,因为 str 是 null,根本没有实际的字符串对象,调用 length() 方法就像让一个不存在的人告诉你他有多高,肯定会出问题!
如何处理异常?
处理异常就像外卖小哥遇到问题后想办法解决,常见的方法有两种:try-catch-finally 和 throws。
try-catch-finally
try 块里放可能会抛出异常的代码;catch 块用来捕获并处理异常,可以有多个 catch 块处理不同类型的异常;finally 块里的代码无论是否发生异常,都会被执行,通常用于释放资源,比如关闭文件流、数据库连接等。
public class TryCatchFinallyExample {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
try {
System.out.println(arr[3]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组下标越界啦!");
} finally {
System.out.println("不管有没有异常,我都会执行哦!");
}
}
}
在这个例子中,访问 arr[3] 会抛出 ArrayIndexOutOfBoundsException,catch 块捕获到异常并打印提示信息,finally 块也会正常执行。
throws
如果你觉得当前方法不想处理异常,可以把异常抛给调用它的方法,就像外卖小哥遇到解决不了的问题,把问题上报给领导。
public class ThrowsExample {
public static void readFile() throws FileNotFoundException {
File file = new File("nonexistent.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
scanner.close();
}
public static void main(String[] args) {
try {
readFile();
} catch (FileNotFoundException e) {
System.out.println("文件读取出问题啦!");
}
}
}
readFile 方法声明了会抛出 FileNotFoundException,把处理异常的责任交给了调用它的 main 方法,main 方法再用 try-catch 来处理。
自定义异常
除了 Java 自带的异常,有时候我们也可以根据业务需求,自定义异常类,就像外卖公司可以制定自己独特的问题处理规则。
class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void checkAge(int age) throws MyException {
if (age < 18) {
throw new MyException("年龄未满18岁,不符合要求!");
}
System.out.println("年龄符合要求!");
}
public static void main(String[] args) {
try {
checkAge(15);
} catch (MyException e) {
System.out.println(e.getMessage());
}
}
}
这里我们自定义了 MyException 类,继承自 Exception,在 checkAge 方法中,如果年龄不符合条件,就抛出这个自定义异常,并在 main 方法中捕获处理。
好啦,关于 Java 异常的知识就聊到这里!以后写代码时,遇到异常别慌,把它当成程序世界里的小挑战,用学到的方法去 “驯服” 它,你就能让程序像训练有素的外卖小哥一样,即使遇到意外也能灵活应对,稳稳地完成任务!加油,Java 小能手们!