Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)

2026-07-29 17:56:13

Java从入门到“放弃”(精通)之旅🚀——JavaSE终篇(异常)一、异常的概念与体系结构1.1 什么是异常?在生活中,当一个人表情痛苦时,我们可能会关心地问:"你是不是生病了?"在程序中也是如此,即使我们绞尽脑汁将代码写得尽善尽美,程序运行时仍可能出现各种问题,比如数据格式不对、网络不通畅、内存不足等。

在Java中,将程序执行过程中发生的不正常行为称为异常。例如:

代码语言:javascript复制// 算术异常

System.out.println(10 / 0); // ArithmeticException: / by zero

// 数组越界异常

int[] arr = {1, 2, 3};

System.out.println(arr[100]); // ArrayIndexOutOfBoundsException

// 空指针异常

int[] arr = null;

System.out.println(arr.length); // NullPointerException1.2 异常的体系结构Java中的异常种类繁多,为了分类管理,Java维护了一个异常体系结构:

代码语言:javascript复制Throwable

├── Error

└── Exception

├── IOException

├── ClassNotFoundException

├── CloneNotSupportedException

└── RuntimeException

├── ArithmeticException

├── NullPointerException

├── ArrayIndexOutOfBoundsException

└── ...Throwable:异常体系的顶层类Error:Java虚拟机无法解决的严重问题,如StackOverflowError和OutOfMemoryErrorException:程序员可以通过代码处理的异常1.3 异常的分类根据发生时机,异常可分为:

编译时异常(Checked Exception):在编译期间就能发现的异常运行时异常(Unchecked Exception):RuntimeException及其子类,在程序运行时才会出现代码语言:javascript复制// 编译时异常示例

@Override

public Person clone() {

return (Person)super.clone(); // 需要处理CloneNotSupportedException

}

// 运行时异常示例

int[] arr = null;

System.out.println(arr.length); // NullPointerException二、异常的处理方式2.1 防御式编程的两种风格LBYL(Look Before You Leap):事前检查代码语言:javascript复制boolean ret = false;

ret = 登陆游戏();

if (!ret) {

处理登陆游戏错误;

return;

}

ret = 开始匹配();

if (!ret) {

处理匹配错误;

return;

}

// ...更多检查EAFP(It’s Easier to Ask Forgiveness than Permission):事后处理代码语言:javascript复制try {

登陆游戏();

开始匹配();

游戏确认();

选择英雄();

载入游戏画面();

} catch (登陆游戏异常) {

处理登陆游戏异常;

} catch (开始匹配异常) {

处理开始匹配异常;

}

// ...更多catch块Java主要采用EAFP风格,通过五个关键字处理异常:throw、try、catch、finally、throws。

2.2 异常的抛出(throw)使用throw关键字抛出异常:

代码语言:javascript复制public static int getElement(int[] array, int index) {

if (null == array) {

throw new NullPointerException("传递的数据为null");

}

if (index < 0 || index >= array.length) {

throw new ArrayIndexOutOfBoundsException("传递的数组下标越界");

}

return array[index];

}

public static void main(String[] args) {

int[] array = {1, 2, 3};

getElement(array, 3); // 抛出ArrayIndexOutOfBoundsException

}2.3 异常的捕获2.3.1 异常声明(throws)代码语言:javascript复制public class Config {

public void openConfig(String filename) throws FileNotFoundException {

if (!filename.equals("config.ini")) {

throw new FileNotFoundException("配置文件名字不对");

}

// 打开文件

}

}

public static void main(String[] args) throws FileNotFoundException {

Config config = new Config();

config.openConfig("config.ini");

}2.3.2 try-catch捕获处理代码语言:javascript复制public static void main(String[] args) {

Config config = new Config();

try {

config.openConfig("config.txt");

System.out.println("文件打开成功");

} catch (FileNotFoundException e) {

System.out.println("文件不存在,错误信息:" + e.getMessage());

e.printStackTrace(); // 打印完整调用栈

}

System.out.println("异常处理后的代码");

}2.3.3 finally块代码语言:javascript复制public static int getData() {

Scanner sc = null;

try {

sc = new Scanner(System.in);

int data = sc.nextInt();

return data;

} catch (InputMismatchException e) {

e.printStackTrace();

} finally {

System.out.println("finally中代码");

if (null != sc) {

sc.close(); // 确保资源被释放

}

}

return 0;

} 面试题:finally中的语句一定会执行吗?

答:正常情况下一定会执行,除非遇到:

在try或catch块中调用System.exit()程序所在线程死亡关闭CPU三、异常处理流程代码语言:javascript复制public static void main(String[] args) {

try {

func();

} catch (ArrayIndexOutOfBoundsException e) {

e.printStackTrace();

}

System.out.println("after try catch");

}

public static void func() {

int[] arr = {1, 2, 3};

System.out.println(arr[100]); // 抛出异常

}异常处理流程总结:

执行try中的代码出现异常则匹配catch块找到匹配则执行catch,否则向上传递无论是否匹配,finally都会执行如果一直未被处理,最终由JVM处理,程序终止四、自定义异常类Java内置异常类不能满足所有需求时,可以自定义异常:

代码语言:javascript复制// 自定义用户名异常

class UserNameException extends Exception {

public UserNameException(String message) {

super(message);

}

}

// 自定义密码异常

class PasswordException extends Exception {

public PasswordException(String message) {

super(message);

}

}

// 使用自定义异常

public class Login {

private String userName = "admin";

private String password = "123456";

public static void loginInfo(String userName, String password)

throws UserNameException, PasswordException {

if (!userName.equals("admin")) {

throw new UserNameException("用户名错误!");

}

if (!password.equals("123456")) {

throw new PasswordException("密码错误!");

}

System.out.println("登陆成功");

}

public static void main(String[] args) {

try {

loginInfo("admin", "123");

} catch (UserNameException e) {

System.out.println("用户名异常:" + e.getMessage());

} catch (PasswordException e) {

System.out.println("密码异常:" + e.getMessage());

}

}

} 注意事项:

自定义异常通常会继承自 Exception 或者 RuntimeException继承自 Exception 的异常默认是受查异常继承自 RuntimeException 的异常默认是非受查异常.总结Java异常处理是编写健壮程序的关键技术。通过合理的异常处理,我们可以:

提高程序的容错性分离正常逻辑和错误处理逻辑提供更清晰的错误信息确保资源被正确释放记住异常处理的原则:对可恢复情况使用受检异常,对编程错误使用运行时异常,避免滥用异常处理机制。