入れ子 - java try 抜ける




JavaのSystem.exit()はtry/catch/finallyブロックとどのように連携しますか? (4)

この質問には既に回答があります:

try / catch / finallyブロックに戻ることを含む頭痛に気付いています。tryブロックまたはcatchブロックの戻り値が実行されたとしても、finallyメソッドの戻り値は常にメソッドの戻り値です。

しかし、System.exit()にも同じことが当てはまりますか? たとえば、tryブロックがあるとします。

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

例外がない場合、どのSystem.exit()が呼び出されますか? 出口がreturnステートメントの場合、System.exit(1)の行は常に呼び出されます(?)。 しかし、出口が戻り値と異なる動作をするかどうかはわかりません。

極端なケースでは、コードを再現することは不可能ではないにしても非常に難しいので、単体テストを書くことはできません。 私は今日、後で実験をやろうと思っていますが、何分かの分があれば、私は好奇心を持っています。おそらくSOの誰かが答えを知っています。実験。


  1. 以下の例では、 System.exit(0)が例外行の前にある場合、プログラムは正常に終了するので、FINALLYは実行されません。

  2. System.exix(0)がtryブロックの最後の行である場合、ここでは2つのシナリオがあります

    • 例外が存在すると、finallyブロックが実行されます。
    • 例外が存在しない場合、finallyブロックは実行されません

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

finallyブロックは何に関係なく実行されます.... tryブロックがthrowable(例外またはエラー)をスローした場合でも.....

finallyブロックは実行されません... System.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!!!");
}

finallyブロックは実行されません。 プログラムはSystem.exit()ステートメントの後で終了します。


System.exitSecurityExceptionをスローせずにJVMを終了した場合にcatchブロックとfinallyブロックがどのように実行されないかについては、他の回答がありますが、リソースに対するtry-with-resourcesブロックでは何も起こりません。閉まっている?

JLSによると、セクション14.20.3.2

変換の効果は、リソース仕様をtryステートメントの "内側"に置くことです。 これにより、拡張try-with-resourcesステートメントのcatch節が、リソースの自動初期化または終了のために例外をキャッチできます。

さらに、最終的なブロックが実行される時点までに、最終的なキーワードの意図に沿って、すべてのリソースがクローズされた(または閉じようとしている)。

つまり、 catchまたはブロックが実行される前にリソースがcloseされます。 catchしてfinally走っていなくても何とかcloseたら?

"try-with-resources"ステートメントのリソースが閉じられていないことを示すコードです。

私は、 super.close呼び出す前に文を出力するBufferedReader単純なサブクラスを使用します。

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

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

次に、try-with-resourcesステートメントで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!");
    }
}

出力:

試してみる

したがって、 catchを実行してfinallyブロックしないだけでなく、 "try-with-resources"ステートメントは、 System.exitが成功するとリソースをclose機会を得ることができません。


catchを含む簡単なテストでは、 system.exit(0)がセキュリティ例外をスローしないと、最後に実行されたステートメント( catchfinallyには実行されない)になります。

system.exit(0)がセキュリティ例外をスローした場合、 catchfinally文が実行されます。 両方がcatchしてfinallysystem.exit()ステートメントを含む場合、これらのsystem.exit()ステートメントに先行するステートメントだけが実行されます。

上記の両方のケースで、 tryコードが別のメソッドによって呼び出されたメソッドに属している場合、呼び出されたメソッドは返されません。

詳細はhere (個人ブログ)。





system.exit