Break 在有资源的尝试中不起作用,但在没有资源的尝试中起作用

Posted

技术标签:

【中文标题】Break 在有资源的尝试中不起作用,但在没有资源的尝试中起作用【英文标题】:Break doesn't work in try with resources, but work in try without resources 【发布时间】:2016-09-29 17:58:01 【问题描述】:

Break 在尝试使用资源时不起作用,但在尝试没有资源时起作用! 这是这种情况的一个简单示例。我在工作项目中发现了这个“错误”。 当我在没有资源的情况下使用 try 时

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

我的周期只有一次迭代,这是正确的,因为我有条件“如果为真,则中断”,但是当我更改 try 而没有追索 try WITH 资源时。

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

我惊呆了!循环变得无穷无尽!为什么?

完整代码:

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();
            
        

【问题讨论】:

if (true) ... 可能会被编译器删除。你那里有实际情况吗? 显示另一个版本,有些东西告诉我你不要在那里打电话。 @pablochan 为什么?休息没用?如果编译器删除了我的条件,它并没有删除“break”。例如如果 (true) "do something" 将被优化,它将变成只是 "do something"。 @JornVernee 我认为这不会改变问题。当我尝试使用资源时,“中断”不起作用。当我使用尝试!没有!资源“中断”正常工作。只需复制我的代码并运行,您就会看到它。 我已经可以看到它了,我也知道它为什么不起作用了。我需要查看其他版本才能告诉您区别。 【参考方案1】:

循环是无限的,因为您的关闭发生在 try 范围的末尾。这会引发异常,从而中断中断操作。异常处理程序(位于 while 循环内部)然后捕获它,并继续到循环结束,并且由于循环条件为“真”,因此永远继续。当你不使用 try-with-resource 时,永远不会调用 close,因此不会抛出异常,也不会中断 break。

【讨论】:

pastebin.com/zJfLBBp9 带有“尝试使用资源”的示例,而这个 pastebin.com/4bS5Vatr 示例没有资源。 :) 在第一个示例中 break 有效,但在第二个示例中不起作用 :(【参考方案2】:

就在执行break 之前,调用Resource 上的close 方法。这可以从字节码中看出:

   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

但是这个close 方法本身会抛出一个异常,它将控制权转移到catch 块。在catch 块完成后,while 循环继续其下一次迭代。所以break 语句永远不会被执行。

try-with-resources 生成的结构如下所示:

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

这与您的版本不同,其中内部 finally 块已经处理了异常,然后执行 break。但在上面,异常由外部catch块处理,之后控制权返回到while循环。

【讨论】:

当我像这样pastebin.com/4bS5Vatr 更改捕获时,我也有无尽的循环 你能描述一下我吗,为什么? "但是这个 close 方法本身会抛出一个异常,这会将控制权转移到 catch 块。" 但是 close() 方法必须在 try 块之后执行,不是吗?以及 try 块中的“中断”。 @GermanSevostyanov 你也有无穷无尽的循环,因为它的工作方式与 try-with-resources 相同。关于您的最后一条评论,正如您在字节码中看到的那样,close 方法在退出 try 块之前被称为 ,而不是在它之后。 @JornVarnee 我不明白,为什么 close() 之前调用而不是中断。如果我在尝试的最后一行有“resources.writeSomething()”,我们如何关闭资源?

以上是关于Break 在有资源的尝试中不起作用,但在没有资源的尝试中起作用的主要内容,如果未能解决你的问题,请参考以下文章

WNet API 在 Windows 8 中不起作用

内部资源视图解析器在 Spring Boot 中不起作用

子资源完整性保护在 Chrome 中不起作用

cron 资源在 aws opswork 中不起作用?

邮件/会话资源工厂在 Struts 应用程序中不起作用

从资源中读取文件在 gitlab CI 中不起作用