
在生活中,当一个人表情痛苦时,我们可能会关心地问:"你是不是生病了?"在程序中也是如此,即使我们绞尽脑汁将代码写得尽善尽美,程序运行时仍可能出现各种问题,比如数据格式不对、网络不通畅、内存不足等。
在Java中,将程序执行过程中发生的不正常行为称为异常。例如:
// 算术异常
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); // NullPointerExceptionJava中的异常种类繁多,为了分类管理,Java维护了一个异常体系结构:

Throwable
├── Error
└── Exception
├── IOException
├── ClassNotFoundException
├── CloneNotSupportedException
└── RuntimeException
├── ArithmeticException
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── ...根据发生时机,异常可分为:
// 编译时异常示例
@Override
public Person clone() {
return (Person)super.clone(); // 需要处理CloneNotSupportedException
}
// 运行时异常示例
int[] arr = null;
System.out.println(arr.length); // NullPointerExceptionboolean ret = false;
ret = 登陆游戏();
if (!ret) {
处理登陆游戏错误;
return;
}
ret = 开始匹配();
if (!ret) {
处理匹配错误;
return;
}
// ...更多检查try {
登陆游戏();
开始匹配();
游戏确认();
选择英雄();
载入游戏画面();
} catch (登陆游戏异常) {
处理登陆游戏异常;
} catch (开始匹配异常) {
处理开始匹配异常;
}
// ...更多catch块Java主要采用EAFP风格,通过五个关键字处理异常:throw、try、catch、finally、throws。
使用throw关键字抛出异常:
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
}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");
}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("异常处理后的代码");
}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中的语句一定会执行吗? 答:正常情况下一定会执行,除非遇到:
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]); // 抛出异常
}异常处理流程总结:
Java内置异常类不能满足所有需求时,可以自定义异常:
// 自定义用户名异常
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());
}
}
}注意事项:
Java异常处理是编写健壮程序的关键技术。通过合理的异常处理,我们可以:
记住异常处理的原则:对可恢复情况使用受检异常,对编程错误使用运行时异常,避免滥用异常处理机制。