try-catch-finally 异常处理的两种方式

时间:2021-08-21
本文章向大家介绍try-catch-finally 异常处理的两种方式,主要包括try-catch-finally 异常处理的两种方式使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

异常处理

1. 明确什么是异常 (重点)

2. 能辨识出常见的异常及其含义。 (熟悉+)

3. 理解异常产生的原理 (了解)

4. 能处理异常 (重点)

5. 能够自定义异常类型 (熟悉)

目的

我们发现异常,捕获异常的目的是要对异常进行补救,而不是打印一下。

什么是异常?

异常是在程序中导致程序中断运行的一种指令流。

例如,现在有如下的操作代码:

public class ExceptionDemo01{
public static void main(String argsp[]){
int i = 10 ;
int j = 0 ;
System.out.println("============= 计算开始 =============") ;
int temp = i / j ; // 进行除法运算
System.out.println("temp = " + temp) ;
System.out.println("============= 计算结束 =============") ;
}
};
运行结果:
============= 计算开始 =============
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemo01.main(ExceptionDemo01.java:6)

以上的代码在“int temp = i / j ;”位置处产生了异常,一旦产生异常之后,异常之后的语句将不再执行了,所以现 在的程序并没有正确的执行完毕之后就退出了。

那么,为了保证程序出现异常之后仍然可以正确的执行完毕,所以要采用异常的处理机制。

处理异常

异常处理一般有两种方式,1.使用catch捕获异常; 2.使用throws关键字在方法声明时抛出异常

1.catch捕获异常

如果要想对异常进行处理,则必须采用标准的处理格式,处理格式语法如下:

try{

      // 有可能发生异常的代码段

}catch(异常类型1 对象名1){

      // 异常的处理操作  异常补救

}catch(异常类型2 对象名2){

     // 异常的处理操作   异常补救

} ...

finally{

     // 异常的统一出口

       System.out.println("这里的代码无论是否出现异常都会执行,一般用于资源回收");

}

在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生 了异常,最终都要执行此段代码。

无论异常是否发生,finally必然执行。读取文件,占用文件,读取数据库等,都在finally中释放,因为finally必然执行。一般用于资源回收。

try+catch的处理流程

1、 一旦产生异常,则系统会自动产生一个异常类的实例化对象。

2、 那么,此时如果异常发生在try语句,则会自动找到匹配的catch语句执行,如果没有在try语句中,则会将异 常抛出.

3、 所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。

2.throws  throw 抛出异常

在程序中异常的基本处理已经掌握了,但是随异常一起的还有一个称为throws关键字,此关键字主要在方法的声明上使 用,表示方法中不处理异常,而交给调用处处理。

1.throws是函数方法抛出异常,一般写在方法的头部,用来抛出一些异常,本身不进行解决,抛给方法的调用者进行解决(try catch)

格式: 返回值 方法名称()throws Exception{ }

Integer类: public static int parseInt(String text)throws NumberFormatException

2.throw是语句抛出异常,出现于函数内部,用来抛出一个具体异常实例,throw被执行后面的语句不起作用,直接转入异常处理阶段

一般是用户自定义的RuntimeException运行时异常,然后使用throw抛出。

 1 public class Demo9 {
 2     public static void main(String[] args) {
 3     }
 4 
 5     /**
 6      * 异常是否抛出去, 应该站在哪个角度思考?
 7      *
 8      *  如果是因为传参导致异常 , 应该通过throws将异常抛出去.
 9      *
10      * @param text
11      * @throws IOException : 因为传递的指令不对, 会导致此问题发生(s2=0时)
12      */
13     public static void shutdown(String text) throws IOException {
14         Runtime.getRuntime().exec(text);
15     }
16     /**
17      * 此方法用于求两个参数的和
18      *  会将两个参数 转换为数字 求和
19      * @param s1  字符串参数1
20      * @param s2  字符串参数2
21      */
22     public static void sum(String s1,String s2){
23         int sum = Integer.parseInt(s1)+Integer.parseInt(s2);
24         System.out.println("和是:"+sum);
25     }
26 }
 1 public class Person {
 2     private String name;
 3     private int age;
 4 
 5     public String getName() {
 6         return name;
 7     }
 8 
 9     public void setName(String name) {
10         this.name = name;
11     }
12 
13     public int getAge() {
14         return age;
15     }
16 
17     public void setAge(int age) {
18         if(age<0 || age>180){
19             RuntimeException e = new RuntimeException("年龄不合理");
20             throw e;
21         }else{
22             this.age = age;
23         }
24 
25     }
26 }

异常体系结构

异常指的是Exception , Exception类, 在Java中存在一个父类Throwable(可能的抛出)

Throwable存在两个子类:

1.Error:表示的是错误,是JVM发出的错误操作,只能尽量避免,无法用代码处理。

2.Exception:一般表示所有程序中的错误,所以一般在程序中将进行try…catch的处理。

RuntimeExcepion与Exception的区别

RuntimeException是Exception的子类,

catch(Exception e) 就是范围最大的捕获异常。如果为了方便,则可以将所有的异常都使用Exception进行捕获。

所有RuntimeException的子类即为非检查型异常;Exception的其余子类都为检查型异常。所谓“检查型异常”是指在源代码例必须显式地进行捕获处理,eclipse和idea都是自动编译的,当我们把代码写完的时候,如果有红线提示或者错误提示,那么就是检查异常。也就是说,当你看到某个方法声明中可能抛出某个检查型异常,那么作为调用方必须考虑如何处理这个异常,否则编译器就是给出错误提示。

所谓“非检查型异常”,也就是运行时异常,编译的时候不会给错误提示,运行的时候有可能出现异常。如: 用户输入0作为除数,就会 出现异常。通常是可以通过编码加以避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。例如NullPointerException、ArrayIndexOutOfBoundsException等。也就是说,程序员应该通过合理编码来努力避免程序出现这类异常,或者说程序出现这类异常就是程序员的责任。

异常处理常见面试题

1. try-catch-finally 中哪个部分可以省略?

答: catch和finally可以省略其中一个 , catch和finally不能同时省略 注意:格式上允许省略catch块, 但是发生异常时就不会捕获异常了,我们在开发中也不会这样去写代码.

2. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

答:finally中的代码会执行 详解:

执行流程:

1. 先计算返回值, 并将返回值存储起来, 等待返回

2. 执行finally代码块

3. 将之前存储的返回值, 返回出去;

需注意:

1. 返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值做任何的改变,返回的值都不 会改变

2. finally代码中不建议包含return,因为程序会在上述的流程中提前退出,也就是说返回的值不是try或 catch中的值

3. 如果在try或catch中停止了JVM,则finally不会执行.例如停电- -, 或通过如下代码退出 JVM:System.exit(0)。

try中有return时,finally也会执行,这个return值在finally执行之前的try中已经准备好了,复制备份放入了缓存。如果return返回的是基本数据类型,如int,那么finally中再给int赋值也不会改变return返回的值。如果return返回的是一个对象,那么复制到缓存中的是这个对象的地址,这时在finally中改变这个对象的值时,返回的值就是改变以后的值。

 
 1 public class Demo7 {
 2     public static void main(String[] args) {
 3         int a = haha();
 4         System.out.println(a);
 5     }
 6     public static int haha(){
 7         int a = 10;
 8         try{
 9             return a;
10         }catch(Exception e){
11 
12         }finally {
13             a = 20;
14         }
15         return 0;
16     }
17     static class Person{
18         int age;
19     }
20 }

以上输出结果是:10

因为finally执行之前,retrun 的a是10,这个值已经复制到缓存中,输出时,就i时输出缓存中的值。finally再改变a的值也不会被输出。

 1 public class Demo6 {
 2     public static void main(String[] args) {
 3         Person p = haha();
 4         System.out.println(p.age);
 5     }
 6     public static Person haha(){
 7         Person p = new Person();
 8         try{
 9             p.age = 18;
10             return p;
11         }catch(Exception e){
12             return null;
13         }finally {
14             p.age = 28;
15         }
16     }
17     static class Person{
18         int age;
19     }
20 }

以上输出结果是:28

try中return的p对象,放到输出缓存中是P对象的地址。finally中改变的是这个地址中的值,所以输出的值就是改变之后的值。

原文地址:https://www.cnblogs.com/sumerwine/p/15170523.html