一、异常的捕获
1.1. 多个异常,一次捕获
由于 Exception 类是所有异常类的父类,因此可以用这个类型表示捕捉所有异常。这种写法不推荐,因为编译器会提示有风险但不指明具体风险。
public class Main {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
try {
System.out.println("before");
arr = null;
System.out.println(arr[100]);
System.out.println("after");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("after try catch");
}
}

1.2. 异常之间的父子关系
如果异常之间具有父子关系,子类异常必须在父类异常之前被 catch,否则语法错误。例如 NullPointerException 是 RuntimeException 的子类,若先 catch RuntimeException,则第二个 catch 无法到达。
public class Main {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch (RuntimeException e) {
System.out.println("捕获运行时异常");
e.printStackTrace();
} catch (NullPointerException e) {
//Exception 'java.lang.NullPointerException' has already been caught
System.out.println("捕获空指针异常");
}
}
}
1.3. finally
finally 用于确保资源回收,无论是否发生异常都会执行。在程序正常或异常退出时,必须对资源(如网络连接、数据库连接、IO 流)进行回收。
语法规则:
try {
//可能发生的异常;
} catch(异常类型 e){
//对捕获的异常进行处理;
} finally {
//此处的语句无论是否发生异常,都会被执行到;
}
示例代码:
public class Main {
public static void main(String[] args) {
try {
if (cond1) {
release();
return;
}
if (cond2) {
throw new Exception("某些未知异常");
}
release();
} catch (Exception e) {
release();
} finally {
release();
}
}
private static void release() {}
}
针对 return 语句导致 finally 前代码未执行的情况,使用 finally 可保证资源释放。
public class Main {
public static void main(String[] args) {
try {
int a = 1;
int b = 2;
if (a < b) {
throw new NullPointerException("a 小于 b");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
release();
}
}
private static void release() {
System.out.println("release 释放资源");
}
}

关于返回值覆盖:
public class Main {
public static int func() {
try {
return 10;
} catch (Exception e) {
return 20;
} finally {
return 30;
}
}
public static void main(String[] args) {
System.out.println(func());
}
}
结果为 30。这是因为 finally 块中的返回值会覆盖 try 或 catch 中的返回值。
二、自定义异常
Java 内置异常类不能完全表示实际开发中遇到的业务异常,需要根据业务类型自定义异常结构。异常本质是类,继承自 Java 标准库的异常(如 Exception、RuntimeException)。
以下是一个登录系统的示例:
//创建异常类
class UsernameException extends Exception {}
class PasswordException extends Exception {}
//设置登录系统
class Login {
private String username = "crane";
private String password = "24170";
public void login(String username, String password) throws UsernameException, PasswordException {
if (!username.equals(this.username)) {
throw new UsernameException();
}
if (!password.equals(this.password)) {
throw new PasswordException();
}
System.out.println("登录成功");
}
}
public class Main {
public static void main(String[] args) {
Login lg = new Login();
try {
lg.login("night", );
} (UsernameException e) {
System.out.println();
} (PasswordException e) {
System.out.println();
}
}
}


