java - runtime getruntime exec




最终总是在Java中执行? (20)

答案很简单。

INPUT:

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");
}

OUTPUT:

catch
finally

考虑到这个代码,我可以绝对确定 finally块总是执行,不管什么something()是什么?

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

finally块总是执行是否异常处理。如果在try块之前发生任何异常,finally块将不会执行。


以下是Java语言规范的官方文字。

14.20.2。 执行try-finally和try-catch-finally

通过首先执行try块来执行带有finally块的try语句。 然后有一个选择:

  • 如果try块的执行正常完成,[...]
  • 如果try块的执行由于值Vthrow而突然完成,
  • 如果try块的执行由于其他原因R而突然完成,则执行finally块。 然后有一个选择:
    • 如果finally块正常完成,则由于原因Rtry语句突然完成。
    • 如果由于S原因, finally块突然完成,那么try语句因S 原因突然完成( 并且原因R被丢弃 )。

return规范实际上使得这个明确:

JLS 14.17退货声明

ReturnStatement:
     return Expression(opt) ;

没有Expression return语句尝试将控制权转移给包含它的方法或构造函数的调用者。

带有Expression return语句尝试将控制转移给包含它的方法的调用者; Expression的值将成为方法调用的值。

前面的描述说“ 试图传输控制 ”而不是“ 传输控制 ”,因为如果在try块包含return语句的方法或构造函数中有任何try语句,那么这些try语句的任何finally子句将被执行,in在控制转移到方法或构造函数的调用者之前,从最内层到最外层。 突然完成finally子句可能会中断由return语句启动的控制权转移。


以下是凯文答案的详细说明。 重要的是要知道,要返回的表达式在finally之前被评估,即使它是在之后返回的。

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int printX() {
    System.out.println("X");
    return 0;
}

public static int test() {
    try {
        return printX();
    }
    finally {
        System.out.println("finally trumps return... sort of");
    }
}

输出:

X
finally trumps return... sort of
0

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


如果抛出异常,最后运行。 如果没有抛出异常,最后运行。 如果发现异常,最后运行。 如果该异常未被捕获,则最终运行。

只有当JVM退出时,它才会运行。


是的, finally会被召唤。

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

  1. 如果你调用System.exit() ;
  2. 如果JVM首先崩溃;
  3. 如果JVM在trycatch块中达到无限循环(或其他不可中断,非终止语句);
  4. 如果操作系统强制终止JVM进程; 例如UNIX上的“kill -9”。
  5. 如果主机系统死亡; 例如电源故障,硬件错误,操作系统恐慌等等。

是的,finally块总是执行。 大多数开发人员使用这个块关闭数据库连接,resultset对象,语句对象,并且还使用java hibernate来回滚事务。


是的,它会。 只有情况下它不会是JVM退出或崩溃


是的,它会被调用。 这就是拥有最终关键字的关键。 如果跳出try / catch块可以跳过finally块,这与将System.out.println放在try / catch之外是一样的。


最后总是运行这就是整个观点,只是因为它出现在代码中之后并不意味着这就是它的实现。 Java运行时有责任在退出try块时运行此代码。

例如,如果您有以下情况:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

运行时会生成如下所示的内容:

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

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



示例代码:

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.");
    }
}

输出:

finally trumps return. 
0

简而言之,在官方的Java文档(点击here )中写道 -

如果JVM在try或catch代码执行时退出,那么finally块可能不会执行。 同样,如果执行try或catch代码的线程被中断或终止,即使应用程序整体继续,finally块也可能不会执行。


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

  1. 置于finally块中的代码必须在try块内执行, 无论执行什么操作
  2. 因此,如果try块中的代码试图返回一个值或抛出一个异常,那么这个项目被放置在“架子上”,直到finally块可以执行
  3. 由于finally块中的代码具有(根据定义)高优先级,它可以返回或抛出任何喜欢的东西。 在这种情况下,任何遗留在货架上的东西都会被丢弃。
  4. 唯一的例外是,如果VM在try块中完全关闭,例如'System.exit'

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

置于finally块中的代码必须在try块内执行,无论执行什么操作。

因此,如果try块中的代码试图返回一个值或抛出一个异常,那么这个项目被放置在“架子上”,直到finally块可以执行为止。因为finally块中的代码具有(根据定义)高优先级,它可以返回或抛出不管它喜欢什么。 在这种情况下,任何遗留在货架上的东西都会被丢弃。

唯一的例外是,如果VM在try块中完全关闭,例如'System.exit'

永远不要抛出任何来自finally块的异常

try {
  someMethod();  //Throws exceptionOne
} finally {
  cleanUp();    //If finally also threw any exception the exceptionOne will be lost forever
}

这很好,只要cleanUp()永远不会抛出任何异常。 在上面的例子中,如果someMethod()抛出一个异常,并且在finally块中,cleanUp()抛出一个异常,那么第二个异常将从方法中出来,并且原始的第一个异常(正确的原因)将永远丢失。 如果您在finally块中调用的代码可能会引发异常,请确保处理它或记录它。 永远不要让它从最后的块中走出来。

实际上退出程序(通过调用System.exit()或通过导致导致进程中止的致命错误:有时在Windows中非正式地称为“热点”或“Dr Watson”)将阻止您的finally块被阻止执行!

没有什么可以阻止我们嵌套try / catch / finally块(例如,将try / finally块放在try / catch块内,反之亦然),这并不罕见。


这在任何语言中都是真实的......最后将总是在返回语句之前执行,无论返回方法体中的哪个位置。 如果情况并非如此,那么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();
    }
}

除了在try块中最终替换返回的返回点之外,异常也是如此。 引发异常的finally块将替换try块中的返回或异常。







try-catch-finally