异常
- 一、分类
- 1. Error
- 2. Exception
- 二、处理机制
- 1. 捕获异常
- 2. 抛出异常
- 三、自定义异常类
一、分类
1. Error
2. Exception
- 编译时异常
- 运行时异常
二、处理机制
1. 捕获异常
- try-catch-finally
try{
//出现异常后,try块异常后面的代码不会再执行,直接跳转到catch块
}catch(Exception e){
//只有出现异常才会执行
//当要跳出catch块时,先去执行finally
}finally{
//无论是否出现异常都会执行
//一般用来关闭资源
}
//处理完后程序 会 继续往下执行
练习一:当catch和finally都包含return语句,怎么执行
public class ExceptionDemo1{
public static int method(){
int i = 1;
try{
String name = null;
if(name.equals("Tom")){
System.out.println("name");
}
}catch(NullPointerException e){
return 3;
}finally{
return 4;
}
}
public static void main(String[] args){
System.out.println(method());
}
}
//答案是输出4
//因为无论如何finally都需要执行
练习二:当catch和finally都包含return语句,怎么执行
public class ExceptionDemo1{
public static int method(){
int i = 1;
try{
String name = null;
if(name.equals("Tom")){
System.out.println("name");
}
}catch(NullPointerException e){
return ++i;
}finally{
return ++i;
}
}
public static void main(String[] args){
System.out.println(method());
}
}
//catch块的return语句其实可以拆分为i++和return i
//当执行到return i时,因为finally必须执行,因此跳到finally继续执行代码
//finally同样可以拆分为i++和return i
//执行return的时候,退出方法
//输出结果是3
练习三:只有catch包含return语句,怎么执行
public class ExceptionDemo1{
public static int method(){
int i = 1;
try{
String name = null;
if(name.equals("Tom")){
System.out.println("name");
}
}catch(NullPointerException e){
return ++i;
}finally{
++i;
System.out.println("i="+i);
}
}
public static void main(String[] args){
System.out.println(method());
}
}
//执行到catch的return时,先用临时变量存结果值,temp=2,然后跳转到finally。
//finally执行完成后,再回到catch中return
//输出结果是
//i=3
//2
练习四:try-catch-finally外包含return语句,怎么执行
public class ExceptionDemo1{
public static int method(){
int i = 1;
try{
String name = null;
if(name.equals("Tom")){
System.out.println("name");
}
}catch(NullPointerException e){
return ++i;
}finally{
++i;
System.out.println("i="+i);
}
return 5;
}
public static void main(String[] args){
System.out.println(method());
}
}
//在catch中return之后,就不会再执行try-catch-finally外的return
//输出结果同练习三
2. 抛出异常
- try-finally
try{
//出现异常后,try块异常后面的代码不会再执行,直接跳转到finally块
}finally{
//无论是否出现异常都会执行
}
//处理完后程序 不会 继续往下执行,而是把异常抛给上一层方法
- throws
异常信息会一直往上层方法抛出,直到JVM打印出异常信息并终止程序
方法调用:JVM > main() > f1() > f2()
- 当f2()发生编译时异常时,如果f2()不采用try-catch处理,并不会默认采用throws处理,必须要显式抛出异常
- 如果main(), f1()不采用try-catch处理,同样需要显示抛出异常
- 最后到JVM的时候,打印出异常信息并终止程序
public class ExceptionDemo1 {
//3. 与步骤2相同
public static void main(String[] args) throws FileNotFoundException {
f1();
}
//2. f2()抛过来编译时异常,相当于f1()出现了编译时异常,也要指定异常处理方式
public static void f1() throws FileNotFoundException{
f2();
}
//1. 出现编译时异常,抛到f1()
public static void f2() throws FileNotFoundException{
FileInputStream fi = new FileInputStream("C://test.txt");
}
}
细节:
- 对于编译时异常,程序并不会默认采用throws处理,必须显式指定处理的方式
- 对于运行时异常,程序如果不处理,默认采用throws方式
- 子类抛出的异常必须与父类的异常一致,或者是后者的子类
- 一个try-catch块可以捕获多个异常,catch的顺序应该时子异常类在先,父异常类在后
- 捕获异常相当于把异常留在当前类处理,通俗理解为一个人扛下了所有
- 抛出异常通俗理解为甩锅,try-finally也是一种甩锅,只不过甩锅之前要做点手脚(执行finally块)
三、自定义异常类
- 尽量继承运行时异常,这样可以采用默认处理机制,而编译时异常必须要处理
- 抛出自定义异常:
throw new CustomException
- throw关键字:手动生成异常类对象,也即人为制造错误,例如(int a = 1/0)