1.异常的处理流程
- 程序先执行try中的代码
- 如果try中的代码出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配;
- 如果找到匹配的异常类型,就会执行catch中的代码
- 如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者。
- 无论是否找到匹配的异常类型,finally中的代码都会被执行到(在该方法执行之前)
- 如果上层调用者也没有处理的了异常,就继续向上传递;
- 一直到main方法也没有合适的代码处理异常,就会交割JVM来进行处理,此时程序就会异常终止。
2.抛出异常
除了Java内置的类会抛出一些异常外,程序员可以手动的抛出某个异常(被抛出的一个异常,实则就是一个对象),使用throw关键字完成这个操作。
public class Test {
public static void main(String[] args) {
try{
int ret=divide(10,0);
}catch(ArithmeticException e){
e.printStackTrace();
}
}
public static Integer divide(int x,int y){
if(y==0){
//这种情况下我们就应该告诉调用这这里出现问题了Integer
//如果通过返回值的方式告诉调用者这里出现问题了
// return null;
throw new ArithmeticException("此处抛出一个算数异常");
}
return x/y;
}
}
运行结果:
在这个代码中,我们可以根据实际情况来抛出需要的异常,在构造异常对象同时可以指定一些描述信息。
3.异常说明
throws 标注当前的方法,可能抛出的异常,我们在实现某个方法的时候,也就需要明确的知道当前的这个方法可能会抛出的异常。此时就可以通过throws来提醒方法的调用者类小心处理这些异常。
public static Integer divide(int x,int y) throws ArithmeticException{
if(y==0){
//这种情况下我们就应该告诉调用这这里出现问题了Integer
//如果通过返回值的方式告诉调用者这里出现问题了
// return null;
throw new ArithmeticException("此处抛出一个算数异常");
}
return x/y;
}
4.使用finally的注意事项
我们都知道,使用finally的时候,finally都会被执行到,但是这也有一些麻烦:
public static int func(){
try{
return 10;
}finally{
//一般来时,要谨慎在finally使用return语句
return 20;
}
}
注意:
- finally执行的时机是在方法返回之前(try或者catch中如果有return会在这个return之前执行finally),如果finally中也存在这个return 语句,就会执行finally中的return,从而不会执行到try中原有的return语句。
- 一般不建议在finally中写return
5.Java异常体系
-
Java的异常体系描述的是Java标准库中提供的异常类都有哪些,并且分为哪几个类别
-
图上的向上的箭头,其实就是“继承"或者"实现"这样的关系;
-
接口Throwable 有两个重要的子类,Error和Exception;
-
Error是系统级别的异常,JVM内部使用的,普通程序源一般不使用Error这个体系;
-
Exception是应用级别的异常,普通程序员一般使用这一组系列。
-
Java语言语言将派生类于Error类或者RuntimeException类的所有的异常称为非受查异常,所有的其他类称为受查异常。
-
受查异常:如果某个方法中抛出了这个受查异常,那么就必须对这个异常进行显式的处理,包含两种方案:
-
1.直接try catch
-
2.使用throws声明可能会抛出这个异常
-
非受查异常:可以不显式处理。
6.自定义异常
import java.util.Scanner;
public class Login {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String name=scanner.next();
System.out.println("请输入密码:");
String password=scanner.next();
try{
login(name,password);
}catch(NameException | PasswordException e){
e.printStackTrace();
}
}
public static void login(String name,String password) throws NameException, PasswordException {
if(!name.equals("admin")){
//如果用户名不匹配,就抛出”用户名异常“
throw new NameException("用户名错误");
}
if(!password.equals("123456"));
throw new PasswordException("密码错误");
}
}
//此时创建的NameException是受查异常,Exception是受查异常,所以他的子类亚视
//也是受查异常
//若继承在RuntimeException则是非受查异常
public class NameException extends Exception{
public NameException(String log){
super(log);
}
}
public class PasswordException extends Exception{
public PasswordException(String message){
super(message);
}
}
注意:
- 自定义异常通常会继承自Exception或者RuntimeException
- 继承自Exception的异常会默认为是受查异常
- 继承自RuntimeException的异常默认为是非受查异常。