一、什么是异常?
所谓异常指的就是程序在运行时出现错误时通知调用者的一种机制。
程序错误分为三种:
1、编译错误: 编译错误是因为程序没有遵循语法规则,编译程序能够自己发现并且提示我们错误的原因和位置,这个也是大家在刚接触编程语言最常遇到的问题。
2、运行时错误: 运行时错误是因为程序在执行时,运行环境发现了不能执行的操作。
3、逻辑错误: 逻辑错误是因为程序没有按照预期的逻辑顺序执行。异常也就是指程序运行时发生错误,而异常处理就是对这些错误进行处理和控制。
二、Java异常体系
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。异常和错误的区别是:异常能被程序本身可以处理,错误是无法处理。
Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为 非受查异常, 所有的其他异常称为 受查异常。
三、异常的基本用法
try{
有可能出现异常的语句 ;
}[catch (异常类型 异常对象) {
} … ]
[finally {
异常的出口
}]
注意事项:
1、try 代码块中放的是可能出现异常的代码。
2、catch 代码块中放的是出现异常后的处理行为。
3、finally 代码块中的代码用于处理善后工作,会在最后执行。
4、其中 catch 和 finally 都可以根据情况选择加或者不加。
四、 异常处理的机制
在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。
1. 抛出异常: 当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。
2. 捕获异常: 在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。
对于错误、运行时异常、可查异常,Java技术所要求的异常处理方式有所不同。
1. 错误: 对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。
2. 运行时异常: 由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。
3. 可查异常: 对于所有的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。
能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。
异常抛出: 任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。从方法中抛出的任何异常都必须使用throws子句。
异常捕获: 捕捉异常通过try-catch语句或者try-catch-finally语句实现。
总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查RuntimeException和Error。
关于 finally 的注意事项:
finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally)。但是如果finally 中也存在 return 语句,那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的 return。
一般我们不建议在 finally 中写 return (被编译器当做一个警告)。
五、自定义异常
//自定义登录异常
//实现一个简单的控制台版用户登陆程序, 程序启动提示用户输入用户名密码。
//如果用户名密码出错, 使用自定义异常的方式来处理。
private static String userName = "matilda";
private static String passWord = "1234567";
static class UserError extends Exception {
public UserError(String message) {
super(message);
}
}
static class PasswordError extends Exception {
public PasswordError(String message) {
super(message);
}
}
public static void login(String userName,String passWord) throws UserError, PasswordError {
if (!TestDemo.userName.equals(userName)){
throw new UserError("用户名错误");
}
if (!TestDemo.passWord.equals(passWord)){
throw new PasswordError("密码错误");
}
System.out.println("登陆成功");
}
public static void main(String[] args) {
try {
login("matilda","1234567");
}catch (UserError userError){
userError.printStackTrace();
}catch (PasswordError passwordError){
passwordError.printStackTrace();
}
}
注意事项:
自定义异常通常会继承自 Exception 或者 RuntimeException。
继承自 Exception 的异常默认是受查异常。
继承自 RuntimeException 的异常默认是非受查异常。