IT

Java 예외가 발생하지 않습니까?

lottoking 2020. 5. 26. 08:07
반응형

Java 예외가 발생하지 않습니까?


try-catch 구성에 작은 이론적 문제가 있습니다.

어제 Java에 대한 실기 시험을 보았는데 다음 예제를 이해하지 못합니다.

try {
    try {
        System.out.print("A");
        throw new Exception("1");
    } catch (Exception e) {
        System.out.print("B");
        throw new Exception("2");
    } finally {
        System.out.print("C");
        throw new Exception("3");
    }
} catch (Exception e) {
    System.out.print(e.getMessage());
}

문제는 "출력 결과는 어떻습니까?"

나는 그것이 AB2C3 일 것이라고 확신했지만, 놀랍지 않습니다.

정답은 ABC3입니다. (실제 테스트와 동일합니다.)

제 질문은 Exception ( "2")이 어디로 갔습니까?


로부터 Java 언어 사양 14.20.2. :

이유 R로 인해 catch 블록이 갑자기 완료되면 finally 블록이 실행됩니다. 그런 다음 선택이 있습니다.

  • finally 블록이 정상적으로 완료되면 이유 R로 인해 try 문이 갑자기 완료됩니다.

  • 최종 블록 S가 이유 S에 대해 갑자기 완료되면 try 문은 이유 S에 대해 갑자기 완료됩니다 (및 이유 R은 폐기 됨) .

따라서 예외를 발생시키는 catch 블록이있는 경우 :

try {
    // ...
} catch (Exception e) {
    throw new Exception("2");
}

그러나 finally 블록도 있으며 예외도 발생합니다.

} finally {
    throw new Exception("3");
}

Exception("2")버리고 Exception("3")전파됩니다.


finally 블록에서 발생한 예외는 try 또는 catch 블록에서 이전에 발생한 예외를 억제합니다.

Java 7 예 : http://ideone.com/0YdeZo

에서 자바 독의 예 :


static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

그러나이 예제에서 readLine 메소드와 두 예외 모두를 처리하는 경우 readFirstLineFromFileWithFinallyBlock 메소드는 finally 블록에서 발생한 예외를 처리합니다. try 블록에서 발생한 예외는 억제됩니다.


try-withJava 7 의 새로운 구문은 예외 억제의 또 다른 단계를 추가합니다. try 블록에서 발생한 예외는 try-with 부분에서 이전에 발생한 예외를 억제합니다.

같은 예에서 :

try (
        java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
            String newLine = System.getProperty("line.separator");
            String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }

An exception can be thrown from the block of code associated with the try-with-resources statement. In the above example, an exception can be thrown from the try block, and up to two exceptions can be thrown from the try-with-resources statement when it tries to close the ZipFile and BufferedWriter objects. If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed, and the exception thrown by the block is the one that is thrown by the writeToFileZipFileContents method. You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block.


In code from question, each block is plainly discarding the old exception, not even logging it, not good when you are trying to resolve some bugs:

http://en.wikipedia.org/wiki/Error_hiding


Since throw new Exception("2"); is thrown from catch block and not try, it won't be caught again.
See 14.20.2. Execution of try-finally and try-catch-finally.

This is what happening:

try {
    try {
        System.out.print("A");         //Prints A
        throw new Exception("1");   
    } catch (Exception e) { 
        System.out.print("B");         //Caught from inner try, prints B
        throw new Exception("2");   
    } finally {
        System.out.print("C");         //Prints C (finally is always executed)
        throw new Exception("3");  
    }
} catch (Exception e) {
    System.out.print(e.getMessage());  //Prints 3 since see (very detailed) link
}

Your Question is very obvious, and the answer is simple to the same extent.. The Exception object with message as "2" is overwritten by the Exception object with message as "3" .

Explanation : When an Exception occur, its object it thrown to catch block to handle. But when exception occur in catch block itself, its object is transferred to OUTER CATCH Block(if any) for exception Handling. And Same happened Here. The Exception Object with message "2" is transferred to OUTER catch Block . But wait.. Before leaving inner try-catch block it HAS TO EXECUTE FINALLY. Here occurred the change we are concerned about. A new EXCEPTION object(with message "3") is thrown out or this finally block which replaced the already thrown Exception object(with message "2").As a result of which, when the message of Exception object is printed , we got overridden value i.e. "3" and not "2".

Keep Remember :Only one exception object can be handled by on CATCH block.


The finally block always runs. Either you return from inside the try block or an exception is thrown. The exception thrown in the finally block will override the one thrown in the catch branch.

Additionally, throwing an exception will not cause any output by itself. The line throw new Exception("2"); will not write anything out.


According to your code:

try {
    try {
        System.out.print("A");
        throw new Exception("1");   // 1
    } catch (Exception e) {
        System.out.print("B");      // 2
        throw new Exception("2");
    } finally {                     // 3
        System.out.print("C");      // 4 
        throw new Exception("3");
    }
} catch (Exception e) {             // 5
    System.out.print(e.getMessage());
}

As you can see here:

  1. print A and throws exception # 1;
  2. this exception has caught by catch statement and print B - # 2;
  3. block finally # 3 executes after try-catch (or only try, if hadn't occurred any exception) statement and prints C - # 4 and thrown new exception;
  4. this one has caught by external catch statement # 5;

Result is ABC3. And 2 is omitted at the same way as 1

참고URL : https://stackoverflow.com/questions/18097496/java-exception-not-caught

반응형