这个问题已经有一个答案在这里:

我知道还有头痛,这涉及返回在尝试/赶/最终块-情况下返回的最后总是回返的方法,即使返回在尝试或抓块应该是一个执行。

然而,并同样适用于系统。exit()?例如,如果我有一个尝试块:

try {
    //Code
    System.exit(0)
}
catch (Exception ex) {
    //Log the exception
}
finally {
    System.exit(1)
}

如果没有例外情况,该系统。exit()将称为?如果出口是返回的发言,然后在线系统。exit(1)总会(?) 被称为。然而,我不知道,如果出口行为不同于返回。

代码是在一个极端的情况,是非常困难的,如果不是不可能的,再现,所以我不能写一个单元的测试。我要尝试运行一个试验之后的今天,如果我得到一个几分钟免费的,但我很好奇,反正,也许有人这么知道的答案,可以提供它之前或在的情况下,我不能运行一个实验。

有帮助吗?

解决方案

没有。 System.exit(0) 不返回,并且最终块不是执行。

System.exit(int) 可以扔掉一个 SecurityException.如果发生这种情况,最后块 以执行。和由于相同的主要是呼吁相同的方法从相同的码基地,另一个 SecurityException 可能是引发第二次呼叫。


这里有一个例子,第二种情况:

import java.security.Permission;

public class Main
{

  public static void main(String... argv)
    throws Exception
  {
    System.setSecurityManager(new SecurityManager() {

      @Override
      public void checkPermission(Permission perm)
      {
        /* Allow everything else. */
      }

      @Override
      public void checkExit(int status)
      {
        /* Don't allow exit with any status code. */
        throw new SecurityException();
      }

    });
    System.err.println("I'm dying!");
    try {
      System.exit(0);
    } finally {
      System.err.println("I'm not dead yet!");
      System.exit(1);
    }
  }

}

其他提示

简单测试,包括 catch 太显示,如果 system.exit(0) 不会引发安全例外,它将是最后一次执行声明(catchfinally 不执行在所有)。

如果 system.exit(0) 不会扔一个安全例外, catchfinally 报表是执行。如果两个 catchfinally 含有 system.exit() 发言,只有前所作发言的这些 system.exit() 报表是执行。

在这两种情况下描述下所述,如果 try 代码属于一种方法称为通过另一种方法,称为方法不返回。

更多细节 在这里, (个人的博客).

其他的答案已经涵盖如何 catchfinally 块不行如果 System.exit 退出JVM没有扔 SecurityException, 但他们不出现会发生什么情况在"尝试与资源"框要的资源:他们关闭了?

根据 捷尔思,部分14.20.3.2:

效果的翻译是把资源的规范"内部"的尝试的发言。这使得抓住条款的延长试图与资源的声明,以抓住的一个例外,由于自动初始化或关闭的任何资源。

此外,所有资源将有被关闭(或试图关闭)由当时的最后框执行,保持与意图的最后关键词。

那就是,资源将 closed前 catchfinally 框运行。如果他们是什么 closed即使以某种方式 catchfinally 不要跑?

这里的一些代码,以表明资源,在"尝试与资源"的声明并不是关闭的。

我用一个简单的类的 BufferedReader 那打印的发言之前呼唤 super.close.

class TestBufferedReader extends BufferedReader {
    public TestBufferedReader(Reader r) {
        super(r);
    }

    @Override
    public void close() throws IOException {
        System.out.println("close!");
        super.close();
    }
}

然后我设置了试验的情况下调用 System.exit 在尝试与资源的发言。

public static void main(String[] args)
{
    try (BufferedReader reader = new TestBufferedReader(new InputStreamReader(System.in)))
    {
        System.out.println("In try");
        System.exit(0);
    }
    catch (Exception e)
    {
        System.out.println("Exception of type " + e.getClass().getName() + " caught: " + e.getMessage());
    }
    finally
    {
        System.out.println("finally!");
    }
}

输出:

在尝试

因此,不仅做 catchfinally 块不行,"尽量与资源"的声明不会得到一个机会 close 其资源,如果 System.exit 成功。

最后,区块将被执行的不管是什么。...即使尽量块引发的任何抛出的(例外或误差)。....

唯一的情况下最后块不行...是的,当我们通话系统。exit()方法。

try{
    System.out.println("I am in try block");
    System.exit(1);
} catch(Exception ex){
    ex.printStackTrace();
} finally {
    System.out.println("I am in finally block!!!");
}

它将不执行最后块。该程序将终止 之后系统。exit()发言。

如果你认为这种行为有问题的,你需要精确地控制你的 System.exit 通话,然后你唯一能做的就是换系统。退出功能自己的逻辑。如果我们这样做,我们可以得到最后块的执行,并获得资源的封闭的一部分,我们的出口流动。

我在考虑做是包裹 System.exit 呼叫和功能在我自己的静态的方法。在我的执行情况 exit 我会扔一个亚类的定义 ThrowableError, 和实现一个自定义未捕获的例外处理程序 Thread.setDefaultUncaughtExceptionHandler 处理这一例外。因此我的代码变为:

//in initialization logic:
Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> {
  if(exception instanceof SystemExitEvent){
    System.exit(((SystemExitEvent)exception).exitCode);
  }
})

// in "main flow" or "close button" or whatever
public void mainFlow(){
  try {
    businessLogic();
    Utilities.exit(0);
  }
  finally {
    cleanUpFileSystemOrDatabaseConnectionOrWhatever();  
  }
}

//...
class Utilities {

  // I'm not a fan of documentaiton, 
  // but this method could use it.
  public void exit(int exitCode){
    throw new SystemExitEvent(exitCode);
  }
}

class SystemExitEvent extends Throwable { 
  private final int exitCode;

  public SystemExitEvent(int exitCode){
    super("system is shutting down")
    this.exitCode = exitCode;
  }
} 

这一战略有增加的"利益",使这种逻辑检验:测试该方法中含有我们的"主流"实际上要求的系统退出,我们所要做的就是赶上抛出对象和主张是写入类型。例如,一个测试对于我们的商务逻辑的包装物可能看起来像:

//kotlin, a really nice language particularly for testing on the JVM!

@Test fun `when calling business logic should business the business`(){
  //setup
  val underTest = makeComponentUnderTest(configureToReturnExitCode = 42);

  //act
  val thrown: SystemExitEvent = try {
    underTest.mainFlow();
    fail("System Exit event not thrown!")
  }
  catch(event: SystemExitEvent){
    event;
  }

  //assert
  assertThat(thrown.exitCode).isEqualTo(42)

主要缺点这个战略是,它是一种方式获取功能的异常流程,这往往有意想不到的后果。最明显的一个,在这种情况下,是任何地方,你已经写了 try { ... } catch(Throwable ex){ /*doesnt rethrow*/ } 将必须进行更新。在这种情况下的图书馆,有定义的执行情况,他们将需要进行改装,也理解这种例外。

总的来说,这似乎是一个很好的战略我。有其他人在这里这么认为吗?

  1. 在面的例子中,如果 System.exit(0) 是之前的异常行,该程序将终止通常情况下,因此最终将不会执行。

  2. 如果的 System.exix(0) 是最后一行中的试块,我们在这里有2个方案

    • 当例外是本最后块执行
    • 当异常不是本最后块不行

.

package com.exception;

public class UserDefind extends Exception {
private static int accno[] = {1001,1002,1003,1004,1005};

private static String name[] = {"raju","ramu","gopi","baby","bunny"};

private static double bal[] = {9000.00,5675.27,3000.00,1999.00,1600.00};
UserDefind(){}

UserDefind(String str){
    super(str);
}


public static void main(String[] args) {
    try {
        //System.exit(0); -------------LINE 1---------------------------------
        System.out.println("accno"+"\t"+"name"+"\t"+"balance");

        for (int i = 0; i < 5; i++) {
            System.out.println(accno[i]+"\t"+name[i]+"\t"+bal[i]);
            //rise exception if balance < 2000
            if (bal[i] < 200) {
                UserDefind ue = new UserDefind("Balance amount Less");
                throw ue;
            }//end if
        }//end for
        //System.exit(0);-------------LINE 2---------------------------------

    }//end try
    catch (UserDefind ue)
    {
        System.out.println(ue);
    }
    finally{
        System.out.println("Finnaly");
        System.out.println("Finnaly");
        System.out.println("Finnaly");
    }
}//end of main

}//end of class
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top