美文网首页Java工程师知识树
Java基础-异常-异常处理关键字

Java基础-异常-异常处理关键字

作者: HughJin | 来源:发表于2021-01-15 08:37 被阅读0次

    Java工程师知识树 / Java基础


    异常处理关键字

    Java异常处理机制用到的几个关键字:try、catch、finally、throw、throws。

    • try:用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
    • catch:用于捕获异常。catch用来捕获try语句块中发生的异常。
    • finally:finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
    • throw:用于抛出异常。
    • throws:用在方法签名中,用于声明该方法可能抛出的异常。

    final、finally、finalize的区别与用法

    final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
    finally:是异常处理语句结构的一部分,表示总是执行。
    finalize:是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等。

    Try-with-resources

    环境

    Java1.7版本及其以后版本

    语法

    JDK1.7开始,java引入了 try-with-resources 声明,将 try-catch-finally 简化为 try-catch,这其实是一种语法糖,在编译时会进行转化为 try-catch-finally 语句。
    新的声明包含三部分:try-with-resources 声明try 块catch 块。它要求在 try-with-resources 声明中定义的变量实现了 AutoCloseable 接口,这样在系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。

    所有实现了 java.lang.AutoCloseable接口(其中,它包括实现了java.io.Closeable 的所有对象),可以使用作为资源。

    try-with-resources 声明在 JDK 9 得到改进。如果你已经有一个资源是 final 或等效于 final 变量,您可以在try-with-resources语句中使用该变量,而无需在try-with-resources语句中声明一个新变量。

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.Reader;
    import java.io.StringReader;
     
    public class Tester {
       public static void main(String[] args) throws IOException {
          System.out.println(readData("test"));
       } 
       static String readData(String message) throws IOException {
          Reader inputString = new StringReader(message);
          BufferedReader br = new BufferedReader(inputString);
          try (br) {//在 Java 9 中,不需要声明资源 br就可以使用它,并得到相同的结果。
             return br.readLine();
          }
       }
    }
    

    作用

    关闭在try-catch语句块中使用的资源,需要在ry-with-resources 声明中的实现AutoCloseable 接口的资源。

    使用范例

    Java1.7之前写法

    public static void main(String[] args) {
        FileInputStream file = null;
        try {
            file = new FileInputStream("D:\\logs\\log-cleaner.log");
            System.out.println("ooo");
            file.read();
            System.out.println("aaa");
        } catch (IOException io) {
            System.out.println("bbb");
            io.printStackTrace();
        } catch (Exception e) {
            System.out.println("ccc");
            e.printStackTrace();
        } finally {
            if (file != null) {
                try {
                    file.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    使用JDK1.9之前的 try-with-resources异常处理机制

    public static void main(String[] args) {
        try(FileInputStream file = new FileInputStream("D:\\logs\\log-cleaner.log")){
            System.out.println("ooo");
            file.read();
            System.out.println("aaa");
        }catch (IOException io){
            System.out.println("bbb");
            io.printStackTrace();
        }catch (Exception e){
            System.out.println("ccc");
            e.printStackTrace();
        }
    }
    

    编译后的class文件

    public static void main(String[] paramArrayOfString)
    {
        try
        {
            FileInputStream localFileInputStream = new FileInputStream("D:\\logs\\log-cleaner.log"); 
            Object localObject1 = null;
            try { 
                System.out.println("ooo");
                localFileInputStream.read();
                System.out.println("aaa");
            }
            catch (Throwable localThrowable2)
            {
                localObject1 = localThrowable2; throw localThrowable2;
            }
            finally
            {
                if (localFileInputStream != null) if (localObject1 != null) try { localFileInputStream.close(); } catch (Throwable localThrowable3) { localObject1.addSuppressed(localThrowable3); } else localFileInputStream.close();
            }
        } catch (IOException localIOException) {
            System.out.println("bbb");
            localIOException.printStackTrace();
        } catch (Exception localException) {
            System.out.println("ccc");
            localException.printStackTrace();
        }
    }
    

    return与finally的执行顺序

    public class TestException {
    
    
        public static void main(String[] args) {
            System.out.println("-------------");
            System.out.println(div());//try中有return,且try中不抛异常。
            /*结果:
            process try
            process finally
            0
             */
            System.out.println("-------------");
            System.out.println(divE());//catch中有return,且try中抛异常。
            /*结果:
            process try
            process catch
            process finally
            2
             */
            System.out.println("-------------");
            System.out.println(divEr());//catch,finally中都有return,且try中抛异常。
            /*
            process try
            process catch
            process finally
            3
             */
        }
        public static int div() {
            int result = 0;
            try {
                System.out.println("process try");
                return result;//如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值。
            } catch (ArithmeticException e) {
                result = 2;
                System.out.println("process catch");//
            } finally {
                result = 3;//finally中语句对返回的变量进行赋值的操作时,也不会影响返回的值
                System.out.println("process finally");//
            }
            return result;
        }
        public static int divE() {
            int result = 0;
            try {
                System.out.println("process try");
                int proces = 1/0;
                return result;
            } catch (ArithmeticException e) {
                result = 2;
                System.out.println("process catch");
                return result;//如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值。
            } finally {
                result = 3;//finally中语句对返回的变量进行赋值的操作时,也不会影响返回的值
                System.out.println("process finally");
            }
        }
    
        public static int divEr() {
            int result = 0;
            try {
                System.out.println("process try");
                result = 1/0;
                return result;
            } catch (ArithmeticException e) {
                result = 2;
                System.out.println("process catch");
    //            throw new ArithmeticException("divEr执行异常");// finally 里有return,这里throw失效
                return result;// finally 里有return,这里return失效
            } finally {
                result = 3;
                System.out.println("process finally");
                return result;//finally块中的return语句会阻止异常的栈调用传输,使divEr认为该方法已经正常返回
            }
        }
    
    }
    

    通过上面代码可以得出结论:

    • 当finally有返回值时,会直接返回。不会再去返回try或者catch中的返回值。
    • 如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值。

    原因通过反编译插件查看Class文件:

    相关文章

      网友评论

        本文标题:Java基础-异常-异常处理关键字

        本文链接:https://www.haomeiwen.com/subject/iihlaktx.html