마지막으로 블록은 항상 Java에서 실행됩니까?




return try-catch-finally (20)

대답은 간단합니다.

입력:

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

이 코드를 고려할 때, 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.");
}

finally 블록은 System.exit() 을 호출하거나 스레드가 충돌하지 않는 한 항상 호출되기 때문에 항상 호출됩니다.


try 블록의 return을 마지막으로 대체 할 때의 리턴에 대한 요점 이외에 예외도 마찬가지입니다. 예외를 던지는 finally 블록은 try 블록 내에서 던져진 반환 또는 예외를 대체합니다.


간략하게, 공식 자바 문서 ( here 클릭 here )에는 다음과 같이 쓰여 있습니다 -

try 또는 catch 코드가 실행되는 동안 JVM이 종료되면 finally 블록이 실행되지 않을 수 있습니다. 마찬가지로, try 또는 catch 코드를 실행하는 스레드가 인터럽트되거나 죽게되면 응용 프로그램 전체가 계속 실행 되더라도 finally 블록이 실행되지 않을 수 있습니다.


그것은 실제로 어떤 언어에서나 사실입니다 ... 마침내 return 문 앞에 항상 실행됩니다. 리턴은 메소드 본문에 상관없이 항상 실행됩니다. 그것이 사실이 아니라면, finally 블록은별로 의미가 없을 것입니다.


그것이 결국 블록의 전체 아이디어입니다. 물론, 다른 것들 중에서 돌아 오기 때문에 건너 뛸 수있는 정리 작업을 수행 할 수 있습니다.

try 블록에서 무슨 일이 일어나 든 관계없이 호출됩니다 System.exit(int) 다른 이유로 System.exit(int) 또는 Java Virtual Machine을 호출 하지 않는 한 ).


네, try 또는 catch 코드 블록을 실행 한 후에 finally 호출됩니다.

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

  1. System.exit() ;
  2. JVM이 먼저 충돌하면;
  3. JVM이 try 또는 catch 블록에서 무한 루프 (또는 중단되지 않는 다른 비 종료 문)에 도달하면;
  4. OS가 강제로 JVM 프로세스를 종료하면; 유닉스에서 "kill -9"와 같이.
  5. 호스트 시스템이 종료되면; 전원 오류, 하드웨어 오류, OS 패닉 등.
  6. finally 블록이 데몬 스레드에 의해 실행되고 다른 모든 비 데몬 스레드가 마침내 호출되기 전에 종료되는 경우.

다른 응답들에 덧붙여, 'finally'는 try..catch 블록에 의해 어떤 예외 / 반환 값을 오버라이드 할 권한이 있음을 지적하는 것이 중요합니다. 예를 들어, 다음 코드는 12를 반환합니다.

public static int getMonthsInYear() {
    try {
        return 10;
    }
    finally {
        return 12;
    }
}

마찬가지로 다음 메소드는 예외를 throw하지 않습니다.

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

다음 메소드가 던져 버리는 동안 :

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

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

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

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

  • try 블록의 실행이 정상적으로 완료되면 [...]
  • try 블록의 실행이 값 Vthrow 때문에 갑자기 완료되면 [...]
  • try 블록의 실행이 다른 이유로 R 에서 갑자기 완료되면 finally 블록이 실행됩니다. 그런 다음 선택이 있습니다.
    • finally 블록이 정상적으로 완료되면 try 문은 이유 R 으로 인해 갑자기 완료됩니다.
    • finally 블록이 이유 S 로 인해 갑자기 완료되면 try 문은 이유 S ( 이유 R 이 삭제됨 )에 따라 갑자기 완료 됩니다 .

return 대한 명세는 실제로 이것을 명백하게 만듭니다 :

JLS 14.17 신고서

ReturnStatement:
     return Expression(opt) ;

Expression 이없는 return 문은 컨트롤을 포함하는 메서드 또는 생성자의 호출자에게 제어를 전달 하려고 시도 합니다.

Expression 있는 return 문은 컨트롤을 포함하는 메소드의 호출자에게 제어를 전달 하려고 시도 합니다. Expression 의 값은 메소드 호출의 값이됩니다.

앞의 설명에서는 try 블록에 return 문이 포함 된 메서드 또는 생성자 내에 try 문이있는 경우 try 문에서 finally 절이 실행되므로 " 제어를 이전 하려고 시도 합니다 "라고되어 있습니다. 순서, 가장 안쪽에서 가장 바깥 쪽, 컨트롤이 메서드 나 생성자의 호출자에게 전달되기 전에. finally 절이 갑자기 완료되면 return 문에서 시작된 제어 전송이 중단 될 수 있습니다.


또한 나쁜 실행이지만 finally 블록 내에 return 문이 있으면 일반 블록의 다른 모든 반환보다 우선합니다. 즉, 다음 블록은 false를 반환합니다.

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

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


마지막으로 System.exit (0) 호출과 같은 비정상적인 프로그램 종료가 발생하지 않는 한 항상 실행됩니다. 따라서, sysout이 인쇄됩니다.


마지막으로 블록은 항상 예외 처리 여부를 실행합니다. try 블록 전에 예외가 발생하면 finally 블록이 실행되지 않습니다.


아니요, 예외적 인 경우는 하나도 없습니다 // System.exit (0); finally 블록이 최종적으로 실행되는 것을 막기 전에.

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

예, 가능합니다. JVM 종료 또는 충돌이 발생하지 않는 경우에만


예, 전화가 걸립니다. finally 키워드를 사용하는 것이 중요합니다. try / catch 블록에서 점프하여 finally 블록을 건너 뛸 수 있다면 System.out.println을 try / catch 외부에 둡니다.


예. 블록은 항상 실행됩니다. 대부분의 개발자는이 블록을 사용하여 데이터베이스 연결, 결과 집합 개체, 명령문 개체를 닫고 Java 하이버 네이트를 사용하여 트랜잭션을 롤백합니다.


예제 코드 :

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

이것은 i의 값을 12로 지정했지만 i의 값을 함수에 반환하지 않았기 때문입니다. 올바른 코드는 다음과 같습니다.

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

이것을 생각해 볼 수있는 논리적 인 방법은 다음과 같습니다.

finally 블록에 배치 된 코드는 try 블록 내에서 발생하는 모든 작업을 실행해야합니다.

따라서 try 블록의 코드가 값을 반환하거나 예외를 throw하려고하면 항목이 finally 블록이 실행될 때까지 '선반에 놓이기'finally 블록의 코드는 (정의상) 우선 순위가 높기 때문에 반환하거나 throw 할 수 있습니다 좋아하는 것은 무엇이든간에. 이 경우 '선반에 놓아 둔'것은 버려집니다.

이것에 대한 유일한 예외는 try 블록에서 VM이 완전히 종료되는 경우입니다 (예 : 'System.exit'

finally 블록에서 예외를 던지지 마십시오.

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

cleanUp ()이 예외를 던지지 않는 한 괜찮습니다. 위의 예에서 someMethod ()가 예외를 throw하고 finally 블록에서도 cleanUp ()이 예외를 throw하면 두 번째 예외가 메서드에서 벗어나 원래의 첫 번째 예외 (올바른 이유)가 영원히 손실됩니다. finally 블록에서 호출 한 코드가 예외를 throw 할 수있는 경우 처리하거나 로그해야합니다. 드디어 최종 블록에서 나오게하지 마라.

실제로 System.exit ()을 호출하거나 프로세스를 중단시키는 치명적인 오류 (Windows에서 "핫 스폿"또는 "Dr Watson"으로 비공식적으로 참조되는)을 발생시켜 프로그램을 종료하면 finally 블록이 표시되지 않습니다. 실행!

try / catch / finally 블록을 중첩하는 것을 막을 수있는 방법은 없습니다 (예 : try / catch 블록 안에 try / finally 블록을 넣거나 그 반대의 경우). 그렇게하는 것은 흔한 일이 아닙니다.


정상적인 실행 과정에서 이것을 고려하십시오 (즉, 예외가 발생하지 않는 경우) : 메소드가 'void'가 아닌 경우 항상 명시 적으로 무언가를 반환하지만 결국에는 항상 실행됩니다.







try-catch-finally