program tip

정말 '최종'블록이 필요합니까?

radiobox 2020. 11. 10. 07:58
반응형

정말 '최종'블록이 필요합니까?


java에서 try ... catch ... finally 블록에는 3 개의 순열이 있습니다.

  1. 시도 ...
  2. 시도 ... 캐치 ... 마침내
  3. 시도 ... 마침내

finally 블록이 실행되면 제어는 finally 블록 다음 줄로 이동합니다. finally 블록을 제거하고 모든 명령문을 try ... catch 블록 다음 줄로 이동하면 finally 블록에있는 것과 동일한 효과가 있습니까?


나는 willcode가 여기서 핵심 포인트를 표현하는 데 가장 가깝다고 생각하며 아마도 모든 사람들이 그것을 의미하지만 명확하지는 않습니다.

문제는 실제로 당신이 묻는 것에 매우 잘못된 것이 있다는 것입니다. "내가 모든 명령문을 finally 블록에 쓰는 대신 catch 블록 뒤에 작성하면 잘못된 것이 있습니까?"

catch 블록 뒤에 모든 문을 작성하면 의미하는 바는

1) 항상 예외를 포착합니다.

2) 예외를 포착 한 후에는 항상 다음 문을 계속 진행합니다.

이것은 예외가 발생한 후에도 항상 "정상적으로"실행을 계속한다는 것을 의미하며, 일반적으로 실제로는 절대 원하지 않는 일입니다.

예외는 예외적이어야합니다. 실제로 예외를 처리 할 수 ​​있다면 항상 이러한 조건을 먼저 고려하고 예외가 전혀 발생하지 않도록 코드를 작성하는 것이 좋습니다. 이 모델을 따를 경우 예외는 정말 예외적입니다. 예상 할 수 없거나 수정할 수없는 조건입니다. 당신이 무엇을 향해 노력해야하는지 정말 예상하지 못합니다. 이는 일반적으로 진정한 예외를 처리 할 수 ​​없음을 의미합니다. 즉, 실행을 계속해서는 안되며 대신 애플리케이션을 종료하는 경우가 많습니다.

일반적으로 수행되는 작업은 오류가 호출 스택에 다시 전파되도록 허용하는 것입니다. 어떤 사람들은 이것이 체인에서 더 높은 누군가가 그것을 처리 할 수있는 기회에 이루어 졌다고 말합니다. 나는 본질적으로 결코 일어나지 않는다고 말하고 싶습니다. 이것을하기위한 두 가지 실제 목적이 있습니다. 하나는있는 경우 사용자가 수정할 수있는 것일 수 있습니다. 따라서 사용자에게보고 할 수있는 위치에 도달 할 때까지 오류를 다시 전파합니다. 또는 두 번째로, 사용자가 문제를 해결할 수 없지만 디버깅을 위해 전체 호출 스택을 가져 오려고합니다. 그런 다음 정상에서 잡아서 정상적으로 실패합니다.

이제 finally 블록은 더 많은 의미를 갖습니다. 모두가 말했듯이 항상 실행됩니다. finally의 가장 명확한 사용은 실제로 try ... finally 블록입니다. 지금 당신이 말하는 것은 코드가 잘 실행되는지, 훌륭하다는 것입니다. 우리는 여전히 몇 가지 정리 작업을 수행해야하며 마지막으로 항상 실행 한 다음 계속 진행합니다. 그러나 예외가 발생하면, 우리는 아직 정리를해야 할 수도 있기 때문에 최종적으로 차단해야합니다.하지만 여기서는 더 이상 예외를 포착하지 않기 때문에 더 이상 진행하지 않을 것입니다. finally 블록은 정리가 이루어 지도록하는 데 필수적입니다.

예외가 항상 실행을 멈춘다는 생각은 어느 정도의 경험이있을 때까지 누군가가 이해하기 어려울 수 있지만 실제로는 항상 일을하는 방법입니다. 오류가 발생하면 처음부터 설명해야하는 사소한 오류이거나 줄을 서기 위해 대기중인 오류가 점점 더 많아집니다.

"삼키는"오류-오류를 포착하고 계속 진행하는 것은 프로그램이 예측할 수 없게되고 버그를 찾아서 수정할 수 없기 때문에 할 수있는 최악의 일입니다.

잘 작성된 코드에는 결과에 관계없이 리소스가 항상 해제되도록하는 데 필요한만큼 try ... finally 블록이 포함됩니다. 그러나 잘 작성된 코드에는 일반적으로 응용 프로그램이 가능한 한 정상적으로 실패하거나 사용자에게 지연되도록 기본적으로 존재하는 적은 수의 try ... catch 블록 만 포함됩니다. 즉, 적어도 항상 사용자에게 메시지를 전달하는 등의 의미입니다. 그러나 일반적으로 오류를 포착하고 계속 진행하는 것은 아닙니다.


나는 이것이 매우 오래된 질문이라는 것을 알고 있지만 오늘 알게 된 답변에 혼란 스러웠습니다. 내 말은, 그것들은 모두 정확하지만이 질문에 대한 매우 간단하고 실용적인 대답이있을 때 이론적 또는 철학적 수준에서 모두 대답합니다.

return, break, continue 또는 catch 블록 (또는 try 블록) 내부에서 코드의 순차적 실행을 변경하는 기타 Java 키워드를 넣으면 finally 블록 내부의 명령문이 계속 실행됩니다.

예를 들면 :

public void myFunc() {

    double p = 1.0D;
    String str = "bla";
    try{
        p = Double.valueOf(str);
    }
    catch(Exception ex){
        System.out.println("Exception Happened");
        return;  //return statement here!!!
    }finally{
        System.out.println("Finally");
    }
    System.out.println("After finally");
}

이 코드를 실행하면 다음과 같이 인쇄됩니다.

Exception Happened 
Finally

이것이 finally 블록이 존재하는 가장 중요한 이유입니다. 대부분의 답변은 그것을 암시하거나 부업에서 언급하지만 어느 누구도 그것을 강조하지 않습니다. 나는 이것이 일종의 초보자 질문이기 때문에 그렇게 직접적인 대답이 매우 중요하다고 생각합니다.


하이라이트는 finally예외가 발생 하고 포착되지 않더라도 블록이 실행된다는 것 입니다. 그런 다음 finally블록을 일회성 기회로 사용하여 스트림 닫기와 같은 필요한 정리를 수행합니다. finally 블록 뒤의 코드에는 도달 할 수 없습니다.

자바 튜토리얼에서

finally 블록은 try 블록이 종료 될 때 항상 실행됩니다. 이렇게하면 예기치 않은 예외가 발생하더라도 finally 블록이 실행됩니다. 그러나 마지막으로 예외 처리 이상의 용도로 유용합니다. 프로그래머가 반환, 계속 또는 중단으로 인해 실수로 정리 코드를 우회하는 것을 방지 할 수 있습니다. 정리 코드를 finally 블록에 넣는 것은 예외가 예상되지 않는 경우에도 항상 좋은 방법입니다.


If I understand the question, you're asking what's the difference between:

try {
    Foo f = new Foo();
    f.bar();
}
finally
{
    Foo.baz();
}

And:

// This doesn't actually compile because a try block needs a catch and/or finally block
try {
    Foo f = new Foo();
    f.bar();
}
Foo.baz();

Or, more likely:

Foo f = new Foo();
f.bar();
Foo.baz();

The difference is that if either new Foo() or f.bar() throw an exception, the finally block will get executed in the first case, but that Foo.baz() won't get executed in the last two cases: instead control will skip over Foo.baz() while the JVM looks for an exception handler.


EDIT

Responding to your comment, what about:

Foo f = new Foo();
try {
    f.bar();
}
catch (Exception ex)
{
    // ...
}

f.baz();

You are right that, assuming the catch block doesn't rethrow the exception, or return from the method indicating a failure occured, then f.baz() gets called regardless of whether there was an exception. Even in that case, however, the finally block serves as documentation that f.baz() is used for cleanup.

More importantly, the fact that an exception was thrown usually is important, so it's very hard to write code that continues on doing whatever it was doing without knowing that an exception was thrown. There are times that exceptions indicate silly things that you can ignore, and in that case you should swallow the exception. More often, however, you will want to signal failure, either by rethrowing the exception (or throwing a different exception) or returning from the method with an error code.

For example, if f.bar() is supposed to convert a String to a Double, and on failure it throws a NumberFormatException, then code after the try block probably needs to know that the String was not actually converted to a Double. And, so, in general you won't want to continue after the catch block. Instead, you'll want to signal failure. This is known as "abort on failure" (compared to "resume on failure," which probably should be called "muddle on after failure with your fingers crossed").

Except, in special cases you may be able to muddle on. For instance, the catch block could set the relevant Double to Double.NaN which is designed specifically to propagate errors correctly in math expressions. Even in that case, the finally block serves as documentation that f.baz() is involved in some kind of cleanup.


The finally block contains lines of code that should be executed regardless whether an exception has been caught or not. Even if you decide to stop code running in that method. So code after the t-c-f might not be executed, but the finally code is "guaranteed" (guaranteed in the sense of a non crashing immediately breaking non handleable error).


Yes, there would be something very critically wrong.

And that is, your code would only run if there is an error.

Statements inside finally always run, regardless of an exception being thrown. That is the point.


finally block especially used at the time of exception prevention. If any runtime error occurs, the program may lead to terminate. So at this time, it will call finally block before going to terminate the program. Usually 'finally' contains connection closing statements, save operations and file input, output close operations.


If your code never throws exception, or you are consuming all exception that will be correct. That is not what always happens.

참고URL : https://stackoverflow.com/questions/3861522/do-you-really-need-the-finally-block

반응형