Java 异常详细介绍
Java 的异常(Exception)是指程序在运行过程中出现的不正常情况,通常是程序无法预料的错误。异常发生时,程序的执行会中断。Java 提供了强大的异常处理机制,以便开发者能够捕获和处理这些异常,保证程序的健壮性和稳定性。
异常的处理机制使得 Java 程序能够在出现问题时,避免整个应用程序崩溃,而是能够优雅地处理错误,或者向用户报告有用的错误信息。
1. 异常分类
Java 中的异常按照是否需要强制处理、异常发生的层次、是否可以恢复等因素,分为以下几类:
1.1 检查异常(Checked Exception)
检查异常是 Java 编译器强制要求处理的异常。如果代码中抛出了检查异常,必须显式地捕获该异常或通过 throws
关键字声明抛出。
- 例如:
IOException
、SQLException
、ClassNotFoundException
等。 - 检查异常通常是由外部因素引起的,比如文件未找到、数据库连接失败等。
示例:
java import java.io.*; public class CheckedExceptionExample { public static void main(String[] args) { try { // FileInputStream 是一个会抛出检查异常的操作 FileInputStream file = new FileInputStream("file.txt"); int data = file.read(); file.close(); } catch (IOException e) { // 必须捕获并处理检查异常 System.out.println("An error occurred while reading the file: " + e.getMessage()); } } }
1.2 运行时异常(Unchecked Exception)
运行时异常是 Java 中的 非检查异常,也叫 运行时异常,它是 RuntimeException
类的子类。运行时异常通常是由程序逻辑错误引起的,编译器不会强制要求处理这些异常。
- 例如:
NullPointerException
、ArrayIndexOutOfBoundsException
、ArithmeticException
等。 - 运行时异常通常表示程序本身的错误,需要通过代码修改来修复。
示例:
java public class UncheckedExceptionExample { public static void main(String[] args) { try { // 可能会引发运行时异常:除数为零 int result = 10 / 0; } catch (ArithmeticException e) { // 捕获并处理运行时异常 System.out.println("Cannot divide by zero: " + e.getMessage()); } } }
1.3 错误(Error)
错误表示系统层面的问题,通常是不可恢复的。Error
类及其子类通常不应由程序进行捕获和处理。常见的错误包括 OutOfMemoryError
、StackOverflowError
等。
- 这些错误通常是由于 JVM 本身的资源耗尽或异常状态引起的。
- 一般情况下,程序应该避免发生这些错误,但如果发生了,通常无法恢复。
示例:
java public class ErrorExample { public static void main(String[] args) { try { // 触发 StackOverflowError,递归调用 recursiveMethod(); } catch (StackOverflowError e) { System.out.println("StackOverflowError occurred: " + e.getMessage()); } } public static void recursiveMethod() { recursiveMethod(); } }
2. 异常处理机制
Java 提供了异常处理机制,让程序能够优雅地处理异常,而不是直接终止。
2.1 try-catch-finally 语句
Java 的异常处理通过 try-catch-finally
语句来实现。try
块用于包含可能发生异常的代码;catch
块用于捕获异常并处理;finally
块包含无论是否发生异常都需要执行的代码。
java try { // 可能发生异常的代码 } catch (ExceptionType1 e1) { // 处理 ExceptionType1 异常的代码 } catch (ExceptionType2 e2) { // 处理 ExceptionType2 异常的代码 } finally { // 不管是否发生异常,都会执行的代码(可选) }
2.2 try-catch-finally 代码示例
java public class TryCatchFinallyExample { public static void main(String[] args) { try { // 可能发生异常的代码 int result = 10 / 0; // ArithmeticException } catch (ArithmeticException e) { // 捕获并处理异常 System.out.println("Error: " + e.getMessage()); } finally { // 无论是否发生异常,都会执行 System.out.println("This block always executes."); } } }
输出:
vbnet Error: / by zero This block always executes.
2.3 多重捕获(Multi-catch)
Java 7 及以上版本支持多重捕获,即在一个 catch
块中捕获多种类型的异常,简化代码结构。
java public class MultiCatchExample { public static void main(String[] args) { try { String str = null; str.length(); // 会抛出 NullPointerException } catch (NullPointerException | ArithmeticException e) { // 捕获多种异常类型 System.out.println("An exception occurred: " + e.getMessage()); } } }
2.4 throw 和 throws 关键字
throw
关键字:用于显式抛出一个异常对象。throws
关键字:用于声明方法可能抛出的异常类型,提醒调用者处理这些异常。
throw 示例
java public class ThrowExceptionExample { public static void main(String[] args) { try { throw new IllegalArgumentException("Invalid argument"); } catch (IllegalArgumentException e) { System.out.println("Caught exception: " + e.getMessage()); } } }
throws 示例
java import java.io.*; public class ThrowsExample { public static void main(String[] args) { try { readFile("file.txt"); } catch (IOException e) { System.out.println("An error occurred while reading the file."); } } // 使用 throws 声明方法可能抛出的异常 public static void readFile(String fileName) throws IOException { FileInputStream file = new FileInputStream(fileName); int data = file.read(); file.close(); } }
3. 常见异常类型
3.1 NullPointerException
NullPointerException
是当程序试图访问或操作 null
引用时抛出的异常。
示例:
java public class NullPointerExceptionExample { public static void main(String[] args) { String str = null; System.out.println(str.length()); // 会抛出 NullPointerException } }
3.2 ArrayIndexOutOfBoundsException
当程序试图访问数组中不存在的索引时,会抛出 ArrayIndexOutOfBoundsException
。
示例:
java public class ArrayIndexOutOfBoundsExceptionExample { public static void main(String[] args) { int[] arr = {1, 2, 3}; System.out.println(arr[5]); // 会抛出 ArrayIndexOutOfBoundsException } }
3.3 ArithmeticException
当程序出现数学运算错误时,会抛出 ArithmeticException
,例如除以零。
示例:
java public class ArithmeticExceptionExample { public static void main(String[] args) { int result = 10 / 0; // 会抛出 ArithmeticException } }
3.4 ClassNotFoundException
当程序试图加载一个不存在的类时,会抛出 ClassNotFoundException
。
示例:
java public class ClassNotFoundExceptionExample { public static void main(String[] args) { try { Class.forName("NonExistentClass"); // 会抛出 ClassNotFoundException } catch (ClassNotFoundException e) { System.out.println("Class not found: " + e.getMessage()); } } }
3.5 IOException
IOException
是在输入/输出操作失败或中断时抛出的异常。
示例:
java import java.io.*; public class IOExceptionExample { public static void main(String[] args) { try { FileReader reader = new FileReader("nonexistentfile.txt"); // 会抛出 FileNotFoundException } catch (IOException e) { System.out.println("IOException occurred: " + e.getMessage()); } } }
4. 自定义异常
Java 允许开发者自定义异常。通常有两种方式:
- 自定义检查异常:继承
Exception
类。 - 自定义运行时异常:继承
RuntimeException
类。
4.1 自定义检查异常
java class CustomCheckedException extends Exception { public CustomCheckedException(String message) { super(message); } } public class CustomCheckedExceptionExample { public static void main(String[] args) { try { throw new CustomCheckedException("This is a custom checked exception"); } catch (CustomCheckedException e) { System.out.println(e.getMessage()); } } }
4.2 自定义运行时异常
java class CustomUncheckedException extends RuntimeException { public CustomUncheckedException(String message) { super(message); } } public class CustomUncheckedExceptionExample { public static void main(String[] args) { try { throw new CustomUncheckedException("This is a custom unchecked exception"); } catch (CustomUncheckedException e) { System.out.println(e.getMessage()); } } }
5. 总结
- 检查异常(Checked Exceptions):必须显式捕获或声明,例如
IOException
、SQLException
等。 - 运行时异常(Unchecked Exceptions):不需要强制处理,通常由程序错误引起,例如
NullPointerException
、ArithmeticException
等。 - 错误(Errors):通常是 JVM 层面的问题,不应由应用程序捕获和处理,例如
OutOfMemoryError
、StackOverflowError
等。 - 异常处理机制:通过
try-catch-finally
语句处理异常。 - 自定义异常:可以根据需要自定义异常类,以满足业务需求。
来一杯咖啡,聊聊Java的碎碎念呀