try/catch
异常处理执行原理
异常处理的执行流程
1.程序执行到 System.out.println(a / b); 代码
2.系统会抛出一个异常对象
创建一个异常对象,并且抛出给开发者,当然这里也可以自己抛出,后面会学习如何手动抛出异常。
ArithmeticException e = new ArithmeticException("/ by zero");
throw e;
3.代码进入catch块进行匹配
Exception ae = e; // 多态
4.匹配成功: 程序会转入catch块执行,执行完catch块后继续执行后面程序代码
匹配失败: 程序交还给JVM处理,打印错误信息,程序结束
注意事项:
1.如果程序在try块中出现了异常,那么无论try块下面有多少行代码都不会被执行,直接去和catch块进行匹配。
2.Catch块中的异常类型从上之下必须满足先子类后父类
3.异常处理的标准格式
a.能够显示处理的尽量显示处理,提高程序的可读性
b.程序的最后面一定要加上Exception作为父类接受一切异常,提高了程序的健壮性
Throwable类
概述
Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。
特点
- 该类是所有异常和错误的超类
- 只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出
- 只有此类或其子类之一才可以是 catch 子句中的参数类型
throws的引入
为什么有了try…catch处理异常还需要学习throws关键字?
在实际开发当中,可能某个异常我处理不了,或者我没有权限处理,更或者说我压根就不想处理,那么我们可以抛给其他人处理,即调用者处理,谁调用谁处理。
格式
[修饰符] 返回值类型 方法名(参数列表) [throws 异常类1,异常类2…]{
}
特点
1.该方法抛出异常类,表示抛出调用者处理,谁调用谁处理
2.一个方法可以声明多个异常类
3.如果一个方法抛出的是一个编译时异常,那么必须处理,调用者也必须处理
4.子类继承父类,重写方法,抛出的异常不能够被扩大
- try{}catch()中,如果有多个catch(),里面的变量大小只能向下依次增大
throw关键字
希望能够输出相关错误信息,方便程序调试,所以我们可以使用throw关键字抛出异常对象
throw和throws的区别
1.throws用在方法声明后面,跟的是异常类名,throw用在方法体内,跟的是异常对象名。
2.throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象名。
3.throws表示抛出异常,由该方法的调用者来处理,throw表示抛出异常,由方法体内的语句处理。
throws表示出现异常的一种可能性,并不一定会发生这些异常,throw则是抛出了异常,执行throw则一定抛出了某种异常。
finally关键字
概述
finally修饰的代码块一定会被执行,除非在执行到finally之前程序异常退出或者调用了系统退出的方法。
自定义异常
自定义异常的步骤
1.自定义异常类继承自Exception或者RuntimeException
(1)如果继承自Exception即为编译时异常
(2)如果继承自RuntimeException即为运行时异常
2.书写构造方法,建议书写两个
(1)无参构造方法,不需要传递错误信息
(2)带参构造方法,并且通过super访问父类构造器,将错误信息一直传入到Throwable类的detailMessage变量中。
3.如果希望异常对象能够安全地序列化或者反序列化,则理应书写一个final修饰的serialVersionUID 变量。
public static void main(String[] args) {
try {
throw new Exc1();
// Exception e = new Exc1();
} catch (Exception e) {
System.out.println("Exception");
}catch (Exc0 e) {//错误,要么删除这个catch,要么和上面的catch调换位置
System.out.println("Exc0");
}
}
}
class Exc0 extends Exception {
}
class Exc1 extends Exc0 {
}
public static String output = "";
public static void foo(int i) {
try {
if (i == 1)
throw new Exception();
output += "1";
} catch (Exception e) {
output += "2";
return;
} finally {
output += "3";
}
output += "4";
}
public static void main(String[] args) {
foo(0);
System.out.println(output);
foo(1);
System.out.println(output);
}
输出134/13423
字符串为静态的,foo(1)调用的时候output=“134”,调用后继续拼接。
int x = 1;
try {
x++;
//return x++;
throw new Exception();
} catch (Exception e) {
return x++;
} finally {
++x;
System.out.println(x);
return x++;
}
}
值为4 和 4
try/catch/finally代码块中的代码碰到关键字return后会继续向下执行,注意(X++是先运算再自增,++x先自增再运算)