Java 异常处理
异常的分类
检查性异常
检查性异常是指在编译时由编译器强制要求程序员处理的异常。这些异常通常是由于用户错误或外部问题引起的,例如尝试打开不存在的文件。在编译时,编译器会强制要求对可能引发这些异常的代码进行异常处理。通常,这些异常通过 try-catch 块或在方法声明中使用 throws 子句来捕获和处理。
运行时异常
与检查性异常不同,运行时异常是在程序执行期间抛出的异常,而不是在编译时强制要求处理的。这些异常通常是由于程序中的逻辑错误引起的,例如 NullPointerException、ArrayIndexOutOfBoundsException 等。虽然可以使用 try-catch 块来处理运行时异常,但并不强制要求这样做。我们可以在代码中加入逻辑来避免或预防这些异常的发生。
错误
错误不同于异常,它们表示了程序无法恢复的严重问题,通常超出了我们的控制范围。例如,当栈溢出时,会引发错误。与异常不同,错误通常不应被程序员显式处理,而是应该通过编写健壮的代码来尽可能地避免它们的发生。
异常的捕获
捕获异常使用的是 try 和 catch 关键字,try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
单重捕获
示例
public class Ice{
public static void main(String[] args)
{
int[] a={1,2,4,5,23};
try {
System.out.println(a[5]);
}catch(Exception e)
{
System.out.println("数组访问越界");
}
}
}
多重捕获
在多重捕获中,try 块后面可以跟随多个 catch 块,每个 catch 块可以捕获不同类型的异常,或者捕获同一类型的异常的不同子类。当 try 块中的代码抛出异常时,Java 运行时系统会依次检查每个 catch 块,然后执行第一个能够捕获该异常的 catch 块。如果没有任何一个 catch 块能够捕获该异常,异常就会传播到上层调用栈,直到找到能够处理该异常的地方或者程序终止。
语法结构:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
示例如下:
public class Ice{
public static void main(String[] args)
{
int[] b= {};
try {
System.out.println(b[5]);
}
catch(NullPointerException e)
{
System.out.println("空指针异常"+e.getMessage());
}
catch(Exception e)
{
System.out.println("程序错误"+e.getMessage());
}
}
}
异常的处理
当处理异常时,Java 中的 throw、throws 和 finally 关键字都扮演着重要的角色。
throw 关键字
throw 关键字用于在当前方法中抛出一个异常。通常情况下,当代码执行到某个条件下无法继续正常执行时,可以使用 throw 关键字抛出异常,以告知调用者当前代码的执行状态。例如:
public void checkAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
// 继续执行其他代码
}
1
2
3
4
5
6
public class Ice
{
public void checkAge(int age)
{
if(age<0)
{
throw new IllegalArgumentException("Age cannot be negative");
}else
{
System.out.println("你的年龄是:"+age);
}
}
public static void main(String[] args)
{
int age=3;
Ice a=new Ice();//创建Ice类的对象
a.checkAge(age);
}
}
throws 关键字
throws 关键字用于在方法声明中指定该方法可能抛出的异常。当方法内部抛出指定类型的异常时,该异常会被传递给调用该方法的代码,并在该代码中处理异常。例如:
public void readFile() throws IOException {
// 读取文件的代码
}
import java.io.*;
public class Ice {
public static void readFile(String path) throws IOException {
// 声明 FileReader 和 BufferedReader 对象
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
// 创建 FileReader 对象并打开文件
fileReader = new FileReader(path);
// 创建 BufferedReader 对象以提高读取性能
bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} finally {
//关闭文件流
if (bufferedReader != null) {
bufferedReader.close();
}
if (fileReader != null) {
fileReader.close();
}
}
}
public static void main(String[] args) {
try {
readFile("C:/1.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
}
finally关键字
finally 关键字用来创建在 try 代码块后面执行的代码块。无论是否发生异常,finally 代码块中的代码总会被执行。在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。例如:
try {
// 可能发生异常的代码
} catch (Exception e) {
// 处理异常的代码
} finally {
// 无论是否发生异常,都会执行的代码
}
在如上代码的finally代码块中添加System.out.println("已关闭文件流");
import java.io.*;
public class Ice {
public static void readFile(String path) throws IOException {
// 声明 FileReader 和 BufferedReader 对象
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
// 创建 FileReader 对象并打开文件
fileReader = new FileReader(path);
// 创建 BufferedReader 对象以提高读取性能
bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} finally {
//关闭文件流
if (bufferedReader != null) {
bufferedReader.close();
}
if (fileReader != null) {
fileReader.close();
}
System.out.println("已关闭文件流");
}
}
public static void main(String[] args) {
try {
readFile("C:/Users/86177/Desktop/2.txt");
} catch (IOException e) {
e.printStackTrace();
}
}
}