[java] finally 블록은 항상 Java로 실행됩니까?

이 코드를 고려할 때 블록이 무엇이든 항상 블록이 실행 된다는 것을 절대 확신 할 수 있습니까?finallysomething()

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



답변

예 . 또는 코드 블록을 finally실행 한 후에 호출됩니다 .trycatch

finally호출되지 않는 유일한 시간 은 다음과 같습니다.

  1. 당신이 호출하면 System.exit()
  2. 당신이 호출하면 Runtime.getRuntime().halt(exitStatus)
  3. JVM이 먼저 충돌하는 경우
  4. JVM이 try또는 catch블록 에서 무한 루프 (또는 인터럽트 할 수없고 종료되지 않는 다른 명령문)에 도달 한 경우
  5. OS가 JVM 프로세스를 강제 종료하는 경우 예를 들어, kill -9 <pid>UNIX에서
  6. 호스트 시스템이 죽으면; 예 : 정전, 하드웨어 오류, OS 패닉 등
  7. 경우 finally이전 블록은 데몬 스레드와 모든 다른 비 데몬 스레드 종료에 의해 실행되는 것입니다 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


답변

또한 나쁜 습관이지만 finally 블록 내에 return 문이 있으면 일반 블록에서 다른 반환 값보다 우선합니다. 즉, 다음 블록은 false를 반환합니다.

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

finally 블록에서 예외를 던지는 것과 같습니다.


답변

다음은 Java 언어 사양의 공식 단어입니다.

14.20.2. try-finally 및 try-catch-finally의 실행

블록이 있는 try명령문은 먼저 finally블록을 실행하여 실행됩니다 try. 그런 다음 선택이 있습니다.

  • try블록의 실행이 정상적으로 완료되면 […]
  • V로try 인해 블록의 실행이 갑자기 완료되면 […]throw
  • 실행의 경우 try블록이 다른 이유에 대해 급격 완료 R , 다음 finally블록이 실행된다. 그런 다음 선택이 있습니다.
    • finally 블록이 정상적으로 try완료되면 이유 R 로 인해 명령문이 갑자기 완료 됩니다.
    • 상기 중간 finally블록이 이유에 대해 급격 완료 Stry갑자기 이유에 대한 문이 완료 S ( 이성 R은 폐기된다 ).

에 대한 사양은 return실제로 이것을 명시 적으로 만듭니다.

JLS 14.17 반환 진술

ReturnStatement:
     return Expression(opt) ;

return아니오 문 Expression 시도 를 포함하는 방법 또는 생성자의 호출자로 제어를 전송합니다.

return와 문 Expression 시도 를 포함하는 방법의 호출자에 제어를 전송하는; 의 값은 Expression메소드 호출의 값이됩니다.

위의 설명은 “말을 시도 전송 제어에 그냥”보다는 ” 전송 제어 어떤이있는 경우 때문에” try방법 또는 그 생성자 내에서 문 try블록이 포함되어 return문이 후 모든 finally사람들의 조항 try문은 바깥 쪽을 안쪽 순서대로 실행됩니다 제어가 메소드 또는 생성자의 호출자에게 전송되기 전에 finally절이 갑자기 완료되면 return명령문에 의해 시작된 제어의 전송이 중단 될 수 있습니다 .


답변

다른 응답 외에도 ‘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();
    }
}


답변

위의 예제를 약간 수정하여 시도했습니다.

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

위 코드는 다음과 같이 출력됩니다.

마침내 돌아온다.
2

이는 when return i;가 실행될 때 i값이 2 이기 때문입니다 .이 후에 finally12가 할당 된 i다음 System.outout이 실행되는 블록 이 실행됩니다.

finally블록을 실행 한 후이 try리턴 문이 다시 실행되지 않으므로 블록은 12를 반환하지 않고 2를 반환합니다.

이클립스에서이 코드를 디버깅 할 경우에 당신은 실행 후하는 느낌을 얻을 것이다 System.outfinally블록 return의 문 try블록을 다시 실행합니다. 그러나 이것은 사실이 아닙니다. 단순히 값 2를 반환합니다.


답변

다음은 Kevin의 답변에 대한 설명입니다 . 반환 될 표현식 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