目录
- 前言
- 异常分类
- 声明异常
- 抛出异常
- 捕获异常
- try-catch
- try-catch-finally
- 自动关闭的try-catch
前言
在Java中,异常(Exceptions)是指在程序执行过程中发生的意外或不正常情况。这些异常可能导致程序的正常流程被中断,从而影响程序的执行结果。Java的异常处理机制允许开发者识别、捕获和处理这些异常,以便程序在出现问题时能够进行恰当的应对,而不至于崩溃或产生未知的错误结果。
异常分类
异常主要可以分为两类:可检查异常
和运行时异常
,这两类异常有不同的特性和处理方式。
可检查异常:
可检查异常
是指在编译时必须显式处理或声明的异常,也称为受查异常
。这些异常通常表示程序在运行过程中可能会遇到外部因素导致的问题,例如文件未找到、网络连接失败等。开发者必须在代码中使用try-catch
块或者在方法声明中使用throws
关键字来处理这些异常,否则编译器会报错。
- 常见的可检查异常:
IOException
:输入输出异常,用于处理文件读写等操作。SQLException
:数据库操作异常,用于处理数据库相关错误
运行时异常:
运行时异常
是指在编译时不强制要求处理的异常,也称为非检查异常
。这些异常通常表示程序逻辑错误或其他不可预知的错误情况,例如除以零、空指针引用等。运行时异常在代码中可以选择性地进行处理,如果没有进行处理,程序将在异常出现时终止并抛出异常信息。
- 常见的运行时异常:
ArithmeticException
:算术异常,用于处理算术运算错误,比如除数为零。NullPointerException
:空指针异常,用于处理空对象引用导致的错误。ArrayIndexOutOfBoundsException
:数组索引越界异常,用于处理数组访问越界错误。IllegalArgumentException
:非法参数异常,用于处理传入方法的参数不合法的情况。
声明异常
异常声明
指的是在方法中使用throws关键字
来声明方法可能抛出的异常类型。当一个方法中可能会抛出检查异常(可检查异常)
时,Java要求在方法中显式声明这些异常,以便调用该方法的代码知道可能需要处理这些异常情况。
- 声明可能抛出的异常
// 声明可能抛出IOException的方法 public static void processFile(String filename) throws IOException { // 一些可能抛出IOException的代码 }
抛出异常
可以使用throw关键字
来手动抛出异常。当程序在运行时遇到异常情况,无法继续正常执行时,可以使用throw语句
显式地抛出一个异常对象,以中断当前的程序流程并传递异常信息给上层调用者。
-
基本语法: `throw 异常对象;
-
基础示例:
// 方法中根据输入的值抛出自定义异常 public static void processInput(int value) { if (value < 0) { // 抛出IllegalArgumentException异常 throw new IllegalArgumentException("输入值不能为负数"); } }
processInput
方法根据传入的value
值来判断是否需要抛出IllegalArgumentException异常
。当value
为负数时,会使用throw
语句抛出自定义异常,并且异常对象中包含了错误信息。
捕获异常
Java异常捕获
的作用在于提高程序的健壮性和稳定性,使程序能够在遇到异常情况时进行适当的处理,而不会因为异常而导致程序崩溃或产生不可预料的结果。
错误处理
: 当代码中可能出现异常的情况时,使用异常捕获可以捕获并处理这些异常,避免程序因为异常而停止运行或导致不正确的输出。合理处理异常可以使程序在出现问题时提供友好的错误提示,帮助用户或开发者更好地理解问题。程序稳定性
: 异常捕获保证了程序的稳定性。在出现异常时,程序不会异常终止,而是会根据异常处理逻辑继续执行,使得程序能够正常运行下去。错误信息传递
: 异常捕获可以通过捕获异常对象来获取异常信息,从而更好地理解异常的原因。这些信息对于调试和排除问题非常有用。资源释放
: 在异常处理过程中,可以使用finally代码块确保资源的释放,无论是否发生异常,资源都能得到正确释放。这样可以避免资源泄漏问题,例如关闭文件、数据库连接或网络连接等。异常链传递
: 在处理异常时,可以在catch块中捕获异常后,再通过throw关键字将新的异常抛出,将异常传递给上层调用者。这种方式称为异常链传递,有助于将异常信息传递到合适的地方进行处理。可读性和维护性
: 通过良好的异常处理机制,代码变得更加易读和易于维护。异常捕获可以将异常处理逻辑集中在一处,使代码结构更加清晰。
try-catch
异常捕获是通过使用try-catch
块来处理可能会抛出异常的代码。try-catch
块允许我们在代码中捕获异常并对其进行处理,以便程序能够在异常发生时继续执行,而不会终止运行。
- 异常捕获的基本语法:
try { // 可能抛出异常的代码 } catch (异常类型1 变量名1) { // 处理异常类型1的情况 } catch (异常类型2 变量名2) { // 处理异常类型2的情况 }
try
:包含可能会抛出异常的代码块。catch
:用于捕获并处理指定类型的异常。可以有多个catch块,用于处理不同类型的异常。异常类型
:指定要捕获的异常类型。通常是一个异常类或其父类。变量名
:指定捕获到的异常对象的引用变量名,可以在catch块中使用它来获取异常信息。
try{}
代码块中,执行正常的业务代码,如果try{}
代码块中任意一个行出现异常后,后续业务代码都不会执行,会直接执行catch
代码块。
catch
代码块中,执行出现异常后的代码逻辑,如果try{}
代码块中没有任何异常出现,则不会执行catch
代码块。如果存在多个catch
时,Java会根据异常的类型自动选择需要执行的catch
代码块。
try-catch-finally
finally
子句是Java中的一个可选代码块,用于在异常处理结束后执行某些必须执行的代码,无论是否发生异常。不论在try块中是否抛出异常,finally
代码块都会被执行,这使得它适用于资源的释放、清理或其他必要的收尾工作。
例如:关闭文件、数据库连接、网络连接或释放其他系统资源。这样,即使在处理异常时出现问题,也能保证资源得到正确地释放,避免资源泄漏。
基本语法:
try {
// 可能抛出异常的代码
} catch (异常类型 变量名) {
// 处理异常的代码
} finally {
// 在异常处理结束后执行的代码块
}
示例:
public class Example {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("example.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
System.err.println("文件未找到:" + e.getMessage());
} catch (IOException e) {
System.err.println("读取文件时出现IO异常:" + e.getMessage());
} finally {
try {
if (br != null) {
br.close(); // 关闭文件资源
}
} catch (IOException e) {
System.err.println("关闭文件时出现IO异常:" + e.getMessage());
}
}
}
}
自动关闭的try-catch
在Java 7及以后的版本中,引入了自动关闭的try-catch
也叫try-with-resources
语句,用于自动关闭实现了AutoCloseable接口
的资源,例如文件、数据库连接等。这样可以简化代码,并确保资源在代码块执行完毕后自动关闭,无需显式地调用close()
方法。
当执行到try块
的结尾时,不论是否发生异常,系统都会自动调用资源的close()
方法,确保资源得到正确释放。如果在执行close()
方法时,又发生了异常,则这个异常将会被抑制,不会影响到主要的异常。
基本语法:
try (资源初始化) {
// 可能抛出异常的代码
} catch (异常类型 变量名) {
// 处理异常的代码
}
- 资源初始化:在这里初始化需要自动关闭的资源,这个资源必须实现AutoCloseable接口,该接口中定义了close()方法。
- try:包含可能会抛出异常的代码块。
- catch:用于捕获并处理指定类型的异常。
示例:
在上面try-catch-finally
的案例中,我们通过finally
子语句来实现BufferedReader
资源的关闭,那么使用自动关闭的try-catch
的方式如下:
public class Example {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
System.err.println("文件未找到:" + e.getMessage());
} catch (IOException e) {
System.err.println("读取文件时出现IO异常:" + e.getMessage());
}
}
}
我们使用了自动关闭的try-catch
语句来读取文件内容。在try块中,我们初始化了BufferedReader资源,用于读取文件内容。在代码块执行完毕后,无需手动调用close()方法,系统会自动关闭BufferedReader资源,确保文件得到正确关闭。