2016-09-29 58 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