美文网首页
try...catch...finally与return

try...catch...finally与return

作者: 叛逆的青春不回头 | 来源:发表于2019-03-14 19:12 被阅读0次

    1.try...catch...finally块中的finally是否一定会执行?

    • try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。
    • 在try块中有System.exit(0)这样的语句,System.exit(0);是终止Java虚拟机JVM的,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。

    2.那finally在try-catch的return的之前还是之后执行?

    (1)finally语句是在try的return语句执行之后,return返回之前执行。

    public class MyClass {
        public static void main(String[] args) {
            System.out.println(testReturn());
        }
      public static String testReturn() {
          try {
              System.out.println("try block");
              return testStatement();
          } finally {
              System.out.println("finally block");
          }
      }
    ​
      public static String testStatement() {
          System.out.println("testStatement block");
          return "after return";
      }
    }
    

    运行结果为:

    try block
    testStatement block
    finally block
    after return
    

    可以看到,try中的return语句先执行了,输出“testStatement”。但并没有立即返回,等到finally执行结束后,再进行返回输出“after return”。那当finally也有return的时候又是怎样的呢?

    (2)finally如果有return语句,则会覆盖try(或catch)中的return语句;如果没有,对于原来的返回值,finally可以修引用所对应的对象,无法改变基本类型。

    public class MyClass {
        public static void main(String[] args) {
           System.out.println("testObject: "+testObject());
         System.out.println("testPrimitive: x="+testPrimitive());
        }
        public static Student testObject() {
            Student result = new Student("Tom", 0);
            try {
                result.setAge(1);
                return result;
            } catch (Exception e) {
                result.setAge(2);
                return result;
            } finally {
                result.setAge(3);       //引用类型的返回值,可被修改
    //            return new Student("Kobe", 33);   //可以被“具体值”覆盖
            }
        }
       public static int testPrimitive() {
            int x = 0;
            try {
                return x=1;
            } catch (Exception e) {
                x = 2;
                return x;
            } finally {
                    x = 3;          //基本类型的返回值,不可被修改
    //                return 3;    //可以被“具体值”覆盖
            }
        }
    ​
        private static class Student {
            private String name;
            private int age;
    ​
            public Student(String name, int age) {
                this.name = name;
                this.age = age;
            }
            @Override
            public String toString() {
                return "Student [name=" + name + ", age=" + age + "]";
            }
            public void setAge(int age) {
                this.age = age;
            }
        }
    }
    

    给出下finally中没有return的情况的结果:

    testObject: Student [name=Tom, age=3]
    testPrimitive: x=1
    

    在finally没有return的情况下,对于基本类型x=1的值,finally中的x=3并没有起作用;而为引用时,finally中result.setAge(3)起作用了。

    (3)异常发生时,try中的return语句不会被执行,catch中的return的执行情况与try中return的执行情况一样。

    public class MyClass {
        public static void main(String[] args) {
            System.out.println("x = "+testCatch());
        }
        public static int testCatch() {
            int x = 20;
            try {
                System.out.println("try block");      
                x = x /0;
                return x += 80;
            } catch (Exception e) {
            System.out.println("catch block");
                return x += 15;
            } finally {
                System.out.println("finally block");
                if (x > 25) {
                    System.out.println("x > 25, x = " + x);
                }
                x += 50;
            }
        }
    }
    

    运行结果:

    try block
    catch block
    finally block
    x>25, x = 35
    x = 35
    

    try中发生异常后,try中的return没有执行,而是先执行catch中的return,确定了返回值后再去执行finally块,执行完了catch再返回,finally里对x的改变对返回值无影响,原因同前面一样,也就是说情况与try中的return语句执行情况一样。

    【====总结====】

    执行时机问题。finally总会执行(除非是System.exit()),正常情况下在try后执行,抛异常时在catch后面执行。

    返回值问题。 可以认为try(或catch)中的return语句的返回值放入线程栈的顶部:如果返回值是基本类型则顶部存放的就是值,如果返回值是引用类型,则顶部存放的是引用。 return的时候是复制了一个变量然后返回,所以之后finally操作的变量如果是基本类型的话不会改变其返回值, 但如果返回值是引用类型的话,因为指向同一个对象,就会改变其返回值。但不管是基本类型还是引用类型,都可以被finally返回的“具体值”具体值覆盖。

    相关文章

      网友评论

          本文标题:try...catch...finally与return

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