Break doesn't work in try with resources, but work in try without resources

别来无恙 提交于 2019-12-12 04:12:42

问题


Break doesn't work in try with resources, but work in try without resources!
This is a simple example for this situation. I caught this "bug" in work project. When I use try without resources

try {
Resources resources = getResources()
// some code here, look below
}

I have only one iteration of my cycle, and it's right because I have the condition "if true then break", but when I changed try without recourse on try WITH resources.

try (Resources resources = getResources()) {
    // some code here, look below
}

I was shocked! The cycle became endless! Why?

Full code:

public class Test {
            public static void testTryWithResAndBreak() {
                while (true) {
                    System.out.println("we are in (while(true))");
                    try (Resources resources = getResources()) {
                        System.out.println("We are in try block");
                        if (true) {
                            System.out.println("We are in the if(true) now! Next step is break");
                            break;
                        }
                        System.out.println("OOOOO___OOOO WE ARE HERE!!!");
                        resources.writeSomething();
                    } catch (Exception e) {
                        System.out.println("Catched exception");
                    }
                }
            }
            private static class Resources implements AutoCloseable {
                @Override
                public void close() throws Exception {
                    System.out.println("Resources closed");
                    throw new Exception("Exception after closed resources!");
                }

                public void writeSomething() {
                    System.out.println("i wrote something");
                }
            }

            private static Resources getResources() {
                return new Resources();
            }

            public static void main(String[] args) {
                testTryWithResAndBreak();
            }
        }

回答1:


The cycle is endless because your close is occurring at the end of the try scope. This throws an exception, which interrupts the break operation. The exception handler (which is INSIDE the while loop) then catches it, and continues to the end of the loop, and since the loop condition is 'true', continues forever. When you don't use try-with-resource, the close is never called, so the exception isn't thrown, and the break is not interrupted.




回答2:


Just before the break is executed, the close method on the Resource is called. This can be seen in the byte code:

   L9 // Print statement
    LINENUMBER 14 L9
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "We are in the if(true) now! Next step is break"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1 // Close method call
    LINENUMBER 17 L1
    ALOAD 2
    IFNULL L10
    ALOAD 2
    INVOKEVIRTUAL Main$Resources.close ()V
   L3 // Then the break
    LINENUMBER 15 L3
    GOTO L10

But this close method throws an exception itself, which transfers control over to the catch block. After the catch block is done, the while loop continues its next iteration. So the break statement will never be executed.

The structure generated by the try-with-resources looks something like this:

try {
    Resources resources = null;
    try {
        resources = getResources();
        if (true) {
            break;
        }
    } catch (Exception e) {            
    } finally {
        if(resources != null)
            resources.close();
    }
} catch (Exception e) {
}

This is different from your version, where the inner finally block already handles the exception, after which the break is executed. But in the above, the exception is handled by the outer catch block, after which control is returned to the while loop.



来源:https://stackoverflow.com/questions/39777022/break-doesnt-work-in-try-with-resources-but-work-in-try-without-resources

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!