Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
finally块总是在Java中执行吗?_Java_Error Handling_Return_Try Catch Finally - Fatal编程技术网

finally块总是在Java中执行吗?

finally块总是在Java中执行吗?,java,error-handling,return,try-catch-finally,Java,Error Handling,Return,Try Catch Finally,考虑到这段代码,我是否可以绝对确保无论something()是什么,都始终执行finally块 try { something(); return success; } catch (Exception e) { return failure; } finally { System.out.println("I don't know if this will get printed out"); } 是,执行try或catch代

考虑到这段代码,我是否可以绝对确保无论
something()
是什么,都始终执行
finally

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

是,执行
try
catch
代码块后,将调用
finally

唯一不会调用
finally
的时间是:

  • 如果调用
    System.exit()
  • 如果调用
    Runtime.getRuntime().halt(exitStatus)
  • 如果JVM先崩溃
  • 如果JVM到达
    try
    catch
    块中的无限循环(或其他一些不可中断、不终止的语句)
  • 如果操作系统强制终止JVM进程;e、 例如,UNIX上的kill-9
  • 如果主机系统死亡;e、 例如,电源故障、硬件错误、操作系统死机等
  • 如果
    finally
    块将由守护进程线程执行,并且在调用
    finally
    之前退出所有其他非守护进程线程

  • 除非程序异常终止(如调用System.exit(0)),否则始终执行finally。因此,您的sysout将被打印出来

    是的,它将被调用。这就是使用finally关键字的全部意义。如果跳出try/catch块可以跳过finally块,那么这与将System.out.println放在try/catch之外是一样的。

    示例代码:

    public static void main(String[] args) {
        System.out.println(Test.test());
    }
    
    public static int test() {
        try {
            return 0;
        }
        finally {
            System.out.println("finally trumps return.");
        }
    }
    
    输出:

    3
    2
    
    最终战胜了回归。
    0
    
    始终执行finally块,除非由于JVM崩溃或调用
    系统而导致程序异常终止。退出(0)


    除此之外,从finally块中返回的任何值都将覆盖在执行finally块之前返回的值,因此在使用try finally时要小心检查所有退出点。

    此外,尽管这是一种不好的做法,但如果finally块中有return语句,它将胜过常规街区的任何其他回报。也就是说,以下块将返回false:

    try { return true; } finally { return false; }
    

    从finally块抛出异常也是如此。

    返回finally将抛出任何异常

    思考这个问题的逻辑方法是:

  • 放置在finally块中的代码必须在try块中执行
  • 因此,如果try块中的代码试图返回一个值或抛出一个异常,则该项将被放置在“工具架”上,直到finally块可以执行为止
  • 因为finally块中的代码(根据定义)具有高优先级,所以它可以返回或抛出它喜欢的任何东西。在这种情况下,“架子上”留下的任何东西都会被丢弃
  • 唯一的例外是,如果VM在try块期间完全关闭,例如通过“System.exit”

  • 除了最后替换try块中的return中关于return的一点之外,异常也是如此。抛出异常的finally块将替换try块中抛出的返回或异常。

    我尝试了上面的示例,但做了一些修改-

    public static void main(final String[] args) {
        System.out.println(test());
    }
    
    public static int test() {
        int i = 0;
        try {
            i = 2;
            return i;
        } finally {
            i = 12;
            System.out.println("finally trumps return.");
        }
    }
    
    上述代码输出:

    最后,王牌回归。
    二,

    这是因为当
    返回i时
    i
    的值为2。在此之后,执行
    finally
    块,其中12被分配给
    i
    ,然后执行
    System.out
    out

      class A {
        public static void main(String args[]){
            DataInputStream cin = new DataInputStream(System.in);
            try{
                int i=Integer.parseInt(cin.readLine());
            }catch(ArithmeticException e){
            }catch(Exception e){
               System.exit(0);//Program terminates before executing finally block
            }finally{
                System.out.println("Won't be executed");
                System.out.println("No error");
            }
        }
    }
    
    try {
      CODE inside the try block
    }
    finally {
      FIN code inside finally block
    }
    NEXT code executed after the try-finally block (may be in a different method).
    
    执行
    finally
    块后,
    try
    块返回2,而不是返回12,因为此返回语句不会再次执行


    如果您将在Eclipse中调试此代码,那么您会感觉在执行
    System.out
    of
    finally
    阻塞
    return
    语句之后,会再次执行
    try
    阻塞。但事实并非如此。它只是返回值2。

    最终总是运行,这就是关键所在,只是因为它在返回后出现在代码中并不意味着它就是这样实现的。Java运行时有责任在退出
    try
    块时运行此代码

    例如,如果您具有以下内容:

    int foo() { 
        try {
            return 42;
        }
        finally {
            System.out.println("done");
        }
    }
    
    运行时将生成如下内容:

    int foo() {
        int ret = 42;
        System.out.println("done");
        return 42;
    }
    

    如果抛出未捕获的异常,则
    finally
    块将运行,异常将继续传播

    因为除非调用
    System.exit()
    (或线程崩溃),否则将始终调用finally块。

    这就是finally块的全部思想。它让你确保你做了清理,否则可能会被跳过,因为你返回,当然还有其他事情


    最终被调用,无论try块中发生了什么(除非调用
    System.exit(int)
    或Java虚拟机出于其他原因退出)。

    除了其他响应,必须指出,“finally”有权覆盖try..catch块的任何异常/返回值。例如,以下代码返回12:

    public static int getMonthsInYear() {
        try {
            return 10;
        }
        finally {
            return 12;
        }
    }
    
    类似地,以下方法不会引发异常:

    public static int getMonthsInYear() {
        try {
            throw new RuntimeException();
        }
        finally {
            return 12;
        }
    }
    
    而以下方法确实会抛出它:

    public static int getMonthsInYear() {
        try {
            return 12;          
        }
        finally {
            throw new RuntimeException();
        }
    }
    

    这是因为您将i的值指定为12,但没有将i的值返回给函数。正确的代码如下:

    public static int test() {
        int i = 0;
        try {
            return i;
        } finally {
            i = 12;
            System.out.println("finally trumps return.");
            return i;
        }
    }
    

    下面是Java语言规范中的官方词汇

    首先执行
    try
    块,执行带有
    finally
    块的
    try
    语句。还有一个选择:

    try{
        int divideByZeroException = 5 / 0;
    } catch (Exception e){
        System.out.println("catch");
        return;    // also tried with break; in switch-case, got same output
    } finally {
        System.out.println("finally");
    }
    
    catch
    finally
    
    • 如果
      try
      块的执行正常完成,[…]
    • 如果
      try
      块的执行由于值V的
      抛出而突然完成,[…]
    • 如果执行
      try
      块由于任何其他原因突然完成,则执行
      finally
      块。还有一个选择:
      • 如果finally块完成n
        public static void main(String args[]) throws Exception {
            Object obj = new Object();
            try {
                synchronized (obj) {
                    obj.wait();
                    System.out.println("after wait()");
                }
            } catch (Exception ignored) {
            } finally {
                System.out.println("finally");
            }
        }
        
        // import java.util.concurrent.Semaphore;
        
        public static void main(String[] args) {
            try {
                // Thread.sleep(Long.MAX_VALUE);
                // Thread.currentThread().join();
                // new Semaphore(0).acquire();
                // while (true){}
                System.out.println("after sleep join semaphore exit infinite while loop");
            } catch (Exception ignored) {
            } finally {
                System.out.println("finally");
            }
        }
        
        import sun.misc.Unsafe;
        import java.lang.reflect.Field;
        
        public static void main(String args[]) {
            try {
                unsafeMethod();
                //Runtime.getRuntime().halt(123);
                System.out.println("After Jvm Crash!");
            } catch (Exception e) {
            } finally {
                System.out.println("finally");
            }
        }
        
        private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            Unsafe unsafe = (Unsafe) f.get(null);
            unsafe.putAddress(0, 0);
        }
        
        public static void main(String args[]) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        printThreads("Daemon Thread printing");
                        // just to ensure this thread will live longer than main thread
                        Thread.sleep(10000);
                    } catch (Exception e) {
                    } finally {
                        System.out.println("finally");
                    }
                }
            };
            Thread daemonThread = new Thread(runnable);
            daemonThread.setDaemon(Boolean.TRUE);
            daemonThread.setName("My Daemon Thread");
            daemonThread.start();
            printThreads("main Thread Printing");
        }
        
        private static synchronized void printThreads(String str) {
            System.out.println(str);
            int threadCount = 0;
            Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
            for (Thread t : threadSet) {
                if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
                    System.out.println("Thread :" + t + ":" + "state:" + t.getState());
                    ++threadCount;
                }
            }
            System.out.println("Thread count started by Main thread:" + threadCount);
            System.out.println("-------------------------------------------------");
        }
        
        main Thread Printing  
        Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED  
        Thread :Thread[main,5,main]:state:RUNNABLE  
        Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE   
        Thread count started by Main thread:3  
        -------------------------------------------------  
        Daemon Thread printing  
        Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE  
        Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE  
        Thread count started by Main thread:2  
        -------------------------------------------------  
        
        Process finished with exit code 0
        
        try{
            int divideByZeroException = 5 / 0;
        } catch (Exception e){
            System.out.println("catch");
            return;    // also tried with break; in switch-case, got same output
        } finally {
            System.out.println("finally");
        }
        
        catch
        finally
        
        public static void main(String[] args) {
            System.out.println(test().toString());
        }
        
        public static StringBuffer test() {
            StringBuffer s = new StringBuffer();
            try {
                s.append("sb");
                return s;
            } finally {
                s.append("updated ");
            }
        }
        
        sbupdated 
        
        public class SomeTest {
        
            private static StringBuilder sb = new StringBuilder();
        
            public static void main(String args[]) {
        
                System.out.println(someString());
                System.out.println("---AGAIN---");
                System.out.println(someString());
                System.out.println("---PRINT THE RESULT---");
                System.out.println(sb.toString());
            }
        
            private static String someString() {
        
                try {
                    sb.append("-abc-");
                    return sb.toString();
        
                } finally {
                    sb.append("xyz");
                }
            }
        }
        
        -abc-
        ---AGAIN---
        -abc-xyz-abc-
        ---PRINT THE RESULT---
        -abc-xyz-abc-xyz
        
        private static String someString() {
        
            StringBuilder sb = new StringBuilder();
        
            try {
                sb.append("abc");
                return sb.toString();
        
            } finally {
                sb = null; // Just an example, but you can close streams or DB connections this way.
            }
        }
        
        System.out.println(foo());
        
        ....
        
        int foo(){
            int x = 2;
            try{
                return x++;
            } finally{
                System.out.println(x);
            }
        }
        
        3
        2