2016-09-29 131 views
0

尝试使用资源时不工作,但尝试工作没有资源!
这是这种情况的一个简单例子。我在工作项目中遇到了这个“bug”。 当我使用尝试没有资源在资源尝试中不工作,但尝试不使用资源

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

我只有一个我的周期的迭代,这是正确的,因为我具备的条件,“如果真再突破”,但是当我改变了尝试无追索权的尝试资源。

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(); 
      } 
     } 
+0

'if(true){...}'可能被编译器删除。你有那里的实际情况? – pablochan

+0

显示其他版本,有些东西告诉我你不要在那里打电话。 –

+0

@pablochan为什么?休息不起作用?如果编译器删除了我的条件,它不会删除“break”。例如,如果(true){“do something”}将被优化,它将变成“做某事”。 – GermanSevostyanov

回答

1

周期是无止境的,因为你的亲密是在尝试范围的结尾处出现。这会引发异常,从而中断中断操作。异常处理程序(它是INSIDE的while循环)捕获它,并继续到循环的结尾,并且由于循环条件为'真',将一直持续。当您不使用try-with-resource时,close从不会被调用,所以异常不会被抛出,并且中断不会中断。

+0

http://pastebin.com/zJfLBBp9以“尝试使用资源”为例,以及这个没有资源的http://pastebin.com/4bS5Vatr示例。:) 在第一个例子中断作品,但在第二个例子不起作用:( – GermanSevostyanov

0

就在执行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 { 
    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循环。

+0

当我改变赶上这个http://pastebin.com/4bS5Vatr,我有无尽的周期过于 – GermanSevostyanov

+0

你可以描述我,为什么 – GermanSevostyanov

+0

“但是这个close方法本身会抛出一个异常,它将控制权转移给catch块”,但close()方法必须在try块后执行,是不是?以及try块中的“break”。 – GermanSevostyanov