최종 블록은 항상 Java에서 실행되는가?
이 코드를 고려해 볼 때, 내가 확실히 확신할 수 있을까?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
또는catch
암호 블록
유일한 시간finally
다음과 같이 부르지 않을 것:
- 호출하는 경우
System.exit()
- 호출하는 경우
Runtime.getRuntime().halt(exitStatus)
- JVM이 먼저 충돌하는 경우
- JVM이 의 무한 루프(또는 기타 중단 불가능한, 중단되지 않는 문)에 도달하는 경우
try
또는catch
막다 - OS가 JVM 프로세스를 강제로 종료하는 경우(예:
kill -9 <pid>
- 호스트 시스템이 사망하는 경우(예: 전원 오류, 하드웨어 오류, OS 패닉, 기타 시스템)
- 만약
finally
블록은 데몬 스레드에 의해 실행되며 다른 모든 비-메모 스레드는 다음 전에finally
라고 불린다
예제 코드:
public static void main(String[] args) {
System.out.println(Test.test());
}
public static int test() {
try {
return 0;
}
finally {
System.out.println("something is printed");
}
}
출력:
something is printed.
0
또한 나쁜 관행이지만, 최종 블록 내에 반환문이 있으면 일반 블록에서 다른 어떤 반환문도 능가할 것이다.즉, 다음 블록은 거짓으로 반환된다.
try { return true; } finally { return false; }
마지막 블록에서 예외를 두는 것도 마찬가지야.
자바 언어 명세서의 공식어는 다음과 같다.
14.20.2.try-finally 및 try-catch-finally 실행
A
try
A로 진술하다.finally
은 block은 를 먼저 된다.try
그럼 선택권이 있다:
- 시시의
try
블록이 정상적으로 완료됨, [...]- 시시의
try
블록이 갑자기 완료되는 이유는throw
값 V의 [...]- 시시의
try
다른 이유로 인해 블록이 갑자기 완료되고, 그 다음 R이finally
블록이 실행되다그렇다면 다음과 같은 선택사항이 있다.
- 최종 블록이 정상적으로 완료되면
try
이유 R 때문에 진술이 갑자기 완료된다.- 만약
finally
블록이 이유 S로 인해 갑자기 완료된 다음try
사유 S(그리고 사유 R은 폐기됨) 때문에 진술이 갑자기 완료된다.
大社의 .return
실제로 다음을 명시한다.
ReturnStatement: return Expression(opt) ;
A
return
statement이 은 진술이다.Expression
제어 권한을 메서드 또는 그것을 포함하는 생성자의 호출자에게 이전하려고 시도한다.A
return
라고 진술하다.Expression
컨트롤을 포함하는 메소드의 호출자에게 제어 권한을 이전하려고 시도함; 값Expression
메서드 호출의 가치가 된다.앞의 설명은 단순히 "변속기 제어"가 아니라 "변속기 제어"가 있는 경우라고 한다.
try
다음을 포함하는 방법 또는 생성자 내의 문장try
블록에는 다음이 포함된다.return
진술, 그 다음엔 어떤 것이든finally
에try
제어권이 방법이나 생성자의 호출자에게 전달되기 전에 가장 안쪽에서 가장 바깥쪽으로 순서대로 문장이 실행될 것이다.갑작스러운 a 완료finally
조항은 a에 의해 개시된 통제권의 이전을 방해할 수 있다.return
명세서
다른 응답 외에도, '마침내'는 시도에서 예외/반환 값을 재정의할 권리가 있다는 점을 지적하는 것이 중요하다.막히다예를 들어, 다음 코드는 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
언가가return i;
실행되다i
값이 2이다.이 후에finally
블록이 실행되며 여기서 12가 지정i
그 다음에System.out
아웃이 실행되다
실행finally
차단을 하다try
블록은 12를 반환하지 않고 2를 반환한다. 왜냐하면 이 반환문이 다시 실행되지 않기 때문이다.
이 Eclipse를 에 이클립스를 실행한 후에 이클립스를 디버깅할 수 수 .System.out
의finally
차단을 하다return
…의 성명try
블록이 다시 실행된다.그러나 이것은 사실이 아니다.단순히 값 2를 돌려준다.
여기 케빈의 대답에 대한 자세한 설명이 있다.반환할 표현을 미리 평가해 두는 것이 중요하다.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(int)
또는 다른 이유로 Java Virtual Machine이 출시됨).
이에 대해 논리적으로 생각할 수 있는 방법은 다음과 같다.
- 최종 블록에 배치된 코드는 시도 블록 내에서 발생하는 모든 것을 실행해야 한다.
- 따라서 시도 블록의 코드가 값을 반환하거나 예외를 발생시키려 할 경우, 최종 블록이 실행될 수 있을 때까지 항목은 '선반에' 배치된다.
- 왜냐하면 최종 블록의 코드는 (정의상) 높은 우선순위를 가지고 있기 때문에 그것은 반환하거나 원하는 것을 던질 수 있다.이 경우 '선반 위에' 남겨진 것은 모두 폐기된다.
- 이에 대한 유일한 예외는 '시스템'에서와 같이 시도 블록 중에 VM이 완전히 종료되는 경우 입니다.퇴장'
마지막으로 System.exit(0..)를 호출하는 것과 같은 비정상적인 프로그램 종료가 없는 한 항상 실행되므로 시스템sout이 인쇄될 것이다.
아니, 항상 예외적인 케이스가 하나 있는 것은 아니다./ System.exit(0); 최종 블록 이전에 최종 실행이 방지된다.
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");
}
}
}
또한 마침내 되돌아오는 것은 어떤 예외도 버릴 것이다.http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
이나 JVM과의 한 System.exit(0)
.
또한 최종 블록 내에서 반환되는 모든 값은 최종 블록 실행 전에 반환된 값을 재정의하므로, 최종적으로 Try를 사용할 때 모든 출구 지점을 확인하는 데 주의하십시오.
마지막으로 항상 실행이 중요한데, 단지 반환 후 코드에 나타난다고 해서 그것이 그렇게 구현되는 것은 아니다.Java 런타임은 종료 시 이 코드를 실행할 책임이 있다.try
막다
예를 들어 다음과 같은 경우:
int foo() {
try {
return 42;
}
finally {
System.out.println("done");
}
}
런타임은 다음과 같은 것을 생성한다.
int foo() {
int ret = 42;
System.out.println("done");
return 42;
}
검색되지 않은 예외가 발생할 경우finally
블록이 실행되며 예외가 계속 전파된다.
네, 전화 받을 겁니다.그것이 드디어 키워드를 갖는 요점이다.try/catch 블록에서 뛰어내리는 경우, 최종 블록을 건너뛸 수 있는 경우, System.out.println을 try/catch 외부에 놓는 것과 동일하다.
왜냐하면 전화를 걸지 않으면 항상 블록이 호출되기 때문이다.System.exit()
(또는 나사산이 충돌함).
공식 자바 문서(여기를 클릭)에 간결하게 다음과 같이 기록된다.
시도 또는 캐치 코드가 실행되는 동안 JVM이 종료되면 최종 블록이 실행되지 않을 수 있다.마찬가지로, 시도나 캐치 코드를 실행하는 스레드가 중단되거나 소멸되는 경우, 응용 프로그램 전체가 계속되어도 최종 블록은 실행되지 않을 수 있다.
당신이 i의 값을 12로 할당했지만, i의 값을 함수에 반환하지 않았기 때문이다.올바른 코드는 다음과 같다.
public static int test() {
int i = 0;
try {
return i;
} finally {
i = 12;
System.out.println("finally trumps return.");
return i;
}
}
대답은 간단하다 YES.
입력:
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
항상은 아냐.
는 자바 언어 은 어어 게게를 하고 있다.try
-catch
-finally
그리고try
-catch
블록은 14.20.2에서 작동한다.
어떤 장소에서도, 그것은 다음을 명시되지 않았다.finally
블록은 항상 실행된다.하지만 모든 경우에 있어서try
-catch
-finally
그리고try
-finally
작성은 에 이 항목을 한다. 완료하기 전에finally
반드시 실행되어야 한다.
try {
CODE inside the try block
}
finally {
FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).
JLS는 CODE 이후 FIN이 실행된다는 것을 보증하지 않는다.JLS는 CODE와 NEXT가 실행되면 항상 CODE 다음에 그리고 NEXT 전에 FIN이 실행된다는 것을 보장한다.
왜 JLS는 그 사실을 보증하지 않는가.finally
블록은 항상 다음에 실행된다.try
차단? 왜냐하면 불가능하기 때문이다.JVM이 완료 직후 중단(킬, 충돌, 전원 꺼짐)될 가능성은 낮지만 가능성이 있다.try
를 실행하기 전에 차단하다.finally
JLS가 피할 수 있는 건 아무것도 없어
따라서, 적절한 행동에 대한 모든 소프트웨어는finally
블록 다음에 항상 실행되는 블록try
완전한 블록은 도청되고 있다.
return
의 지령try
블록은 이 문제와 무관하다.실행 후 코드에 도달하는 경우try
-catch
-finally
는 것이 보증되어 있다finally
블록은 이전과 함께 또는 이전 없이 실행되었을 것이다.return
사항try
막다
finally
블록은 항상 실행되며 반환하기 전에 실행됨x
의 값
System.out.println("x value from foo() = " + foo());
...
int foo() {
int x = 2;
try {
return x++;
} finally {
System.out.println("x value in finally = " + x);
}
}
출력:
값 최종 = 값 최종 = 3
x= 2foo() = 2의 x 값
네, 그럴 거예요.달리 System.exit()가 호출되거나 JVM이 충돌하지 않는 한, 당신의 시도나 캐치 블록에서 무슨 일이 일어나든 간에, 만약 블록에 반환문이 있다면, 그 반환문 전에 최종적으로 실행될 것이다.
네, 그럴 거예요.JVM이 종료되거나 충돌하지 않는 경우에만 해당
예, 마지막으로 블록은 항상 실행된다.대부분의 개발자는 이 블록을 사용하여 데이터베이스 연결, 결과 집합 개체, 문 개체를 닫을 수 있으며 트랜잭션을 롤백하기 위해 자바 최대 절전 모드로 사용할 수도 있다.
finally
실행될 것이고 그것은 확실하다.
finally
다음과 같은 경우 실행되지 않음:
사례 1 :
실할할 때를 할 때System.exit()
.
사례 2 :
JVM/스레드가 충돌하는 경우.
사례 3:
실행이 수동으로 중지된 경우.
@vibhash의 대답에 다른 대답이 없듯이 덧붙이면 아래의 것과 같은 돌연변이 물체의 경우에 어떤 일이 일어나는지 설명한다.
public static void main(String[] args) {
System.out.println(test().toString());
}
public static StringBuffer test() {
StringBuffer s = new StringBuffer();
try {
s.append("sb");
return s;
} finally {
s.append("updated ");
}
}
윌 출력
sbupdated
나 이거 해봤어, 한 가닥 실이야.
public static void main(String args[]) throws Exception {
Object obj = new Object();
try {
synchronized (obj) {
obj.wait();
System.out.println("after wait()");
}
} catch (Exception ignored) {
} finally {
System.out.println("finally");
}
}
그main
Thread
할 것이다wait
영원히 진술하고, 따라서 절대 부르지 않을 것이다.
따라서 콘솔 출력이 작동하지 않음print
String
후 : 후wait()
또는finally
@Stephen C와 합의된, 위의 예는 여기에서 언급된 세 번째 사례 중 하나이다.
다음 코드에 이러한 무한 루프 가능성 추가:
// import java.util.concurrent.Semaphore;
public static void main(String[] args) {
try {
// Thread.sleep(Long.MAX_VALUE);
// Thread.currentThread().join();
// new Semaphore(0).acquire();
// while (true){}
System.out.println("after sleep join semaphore exit infinite while loop");
} catch (Exception ignored) {
} finally {
System.out.println("finally");
}
}
사례 2: JVM이 먼저 충돌하는 경우
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public static void main(String args[]) {
try {
unsafeMethod();
//Runtime.getRuntime().halt(123);
System.out.println("After Jvm Crash!");
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
unsafe.putAddress(0, 0);
}
Ref: JVM을 어떻게 충돌시키십니까?
의 경우 6: 만약의 경우finally
데몬에 의해 블록 실행 예정Thread
기타 모든 비응급자Threads
전에 퇴장하다.finally
라고 불린다
public static void main(String args[]) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
printThreads("Daemon Thread printing");
// just to ensure this thread will live longer than main thread
Thread.sleep(10000);
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
};
Thread daemonThread = new Thread(runnable);
daemonThread.setDaemon(Boolean.TRUE);
daemonThread.setName("My Daemon Thread");
daemonThread.start();
printThreads("main Thread Printing");
}
private static synchronized void printThreads(String str) {
System.out.println(str);
int threadCount = 0;
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread t : threadSet) {
if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
System.out.println("Thread :" + t + ":" + "state:" + t.getState());
++threadCount;
}
}
System.out.println("Thread count started by Main thread:" + threadCount);
System.out.println("-------------------------------------------------");
}
출력: "대몬 스레드"에서 "마침" 블록이 실행되지 않았음을 의미하는 "마침"을 인쇄하지 않음
main Thread Printing Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED Thread :Thread[main,5,main]:state:RUNNABLE Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE Thread count started by Main thread:3 ------------------------------------------------- Daemon Thread printing Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE Thread count started by Main thread:2 ------------------------------------------------- Process finished with exit code 0
다음 프로그램을 고려하십시오.
public class SomeTest {
private static StringBuilder sb = new StringBuilder();
public static void main(String args[]) {
System.out.println(someString());
System.out.println("---AGAIN---");
System.out.println(someString());
System.out.println("---PRINT THE RESULT---");
System.out.println(sb.toString());
}
private static String someString() {
try {
sb.append("-abc-");
return sb.toString();
} finally {
sb.append("xyz");
}
}
}
Java 1.8.162를 기준으로 위의 코드 블록은 다음과 같은 출력을 제공한다.
-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz
을 사용한다는 뜻이다.finally
객체를 자유롭게 하는 것은 다음과 같은 좋은 관행이다.
private static String someString() {
StringBuilder sb = new StringBuilder();
try {
sb.append("abc");
return sb.toString();
} finally {
sb = null; // Just an example, but you can close streams or DB connections this way.
}
}
사실 그건 어느 언어에서나 맞는 말이야...최종적으로, 그 반환이 메소드 본문에 어디에 있든지 간에, 반환문명 전에 항상 실행될 것이다.만약 그렇지 않았다면, 마침내 블록은 큰 의미를 갖지 못했을 것이다.
try block에서 return을 최종적으로 대체하는 반환점에 추가하여 예외도 마찬가지다.마지막으로 예외를 발생시키는 블록은 시도 블록 내에서 발생하는 반환 또는 예외를 대체한다.
참조URL: https://stackoverflow.com/questions/65035/does-a-finally-block-always-get-executed-in-java
'programing' 카테고리의 다른 글
계산된 속성을 통해 Vuex 상태 변경에 대한 구성 요소 업데이트 (0) | 2022.04.25 |
---|---|
하위 디렉터리의 Vuex 액세스 모듈 (0) | 2022.04.25 |
C 및 C++에서 유니언의 목적 (0) | 2022.04.25 |
v-select 또는 v-comobox에서 "모두 선택" 옵션을 사용하는 방법 (0) | 2022.04.25 |
Axios 인터셉터 - vuex 스토어에서 응답을 반환하는 방법 (0) | 2022.04.25 |