2013-05-16 65 views
49

參考我的問題Any risk in a AutoCloseable wrapper for java.util.concurrent.locks.Lock?,我想知道爲什麼trh try-with-resource需要命名爲局部變量。爲什麼try-with-resource需要一個局部變量?

我現在的用法如下:

try (AutoCloseableReentrantReadWiteLock.Lock l = _lock.writeLock()) { 
    // do something 
}   

變量l是try塊內未使用的,只有污染的命名空間。從我所記得的類似的C#using語句不需要本地命名變量。

是否有任何原因,以下情況可能不被支持,並且在try塊結束時關閉一個匿名局部變量?

try (_lock.writeLock()) { 
    // do something 
}   
+11

這是[在Java 9中解決](https://blogs.oracle.com/darcy/entry/concise_twr_jdk9)。參見[JDK-8068949](https://bugs.openjdk.java.net/browse/JDK-8068948)。 – McDowell

+2

@McDowell Java 9通過允許使用_existing_有效的最終變量來解決當前需要定義_new_變量的行爲。從鏈接中不會顯示Java 9將支持可自動關閉的資源_而不會顯示標識符_。 ([在這裏討論。](http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-January/030864.html)) –

回答

1

我認爲無法使用本地變量是試用資源的觸發器。

此前的Java 1.7,你必須寫這樣的事情:

InputStream in = null; 
try { 
    in = ....; 
} finally { 
    if (in != null) { 
     in.close(); 
    } 
} 

有2個缺點在這裏:

  1. finally塊是討厭,必須是空安全的每個收盤資源
  2. 我們必須聲明區塊外的資源只能在finally區塊中訪問它們。因此我們擴大了變量可訪問的範圍,這是不好的做法。

嘗試 - 與資源語法解決了兩個問題:是不是需要在所有

  1. finally塊。
  2. 資源變量只能在try塊中保持可訪問,即應該知道的地方。

這就是爲什麼可關閉資源必須是本地的。否則,嘗試資源語法的一個主要缺點是「禁用」。

+7

你已經提供了一個很好的理由* allow *聲明試用資源。 OP詢問爲什麼它是*必需的*。 –

+0

主要動機顯然是避免了大量的樣板,併爲程序員提供了現成的解決方案,以解決相當複雜和細微的問題。我認爲範圍問題是最大的。整個故事的10%。 –

+0

對不起,我意識到[ResourceSpecification](http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3)塊引入了一個局部變量,我的問題是爲什麼它必須命名。 –

8

在他們考慮的用例中,大多數需要訪問塊內的資源,例如打開文件 - 讀/寫文件 - 關閉文件。如果他們認爲局部變量未被使用的情況很多,他們就不會做出這個設計決定。

至於爲什麼Lock不能自動關閉,我認爲Doug Lea不太關心語法問題,他專注於解決難題。其他人總是可以在其公用程序上添加語法糖。

展望未來,嘗試與資源可能會失去時尚,取而代之的是lambda。例如

lock.withLock(()->{ execute-while-holding-the-lock; }); 
+1

爲lamda使用+1。其餘的是投機性的。雖然可能是正確的,但我更感興趣的是,如果有理由不能做到。 –

+0

確定它可以完成,這只是更多的工作,他們並不認爲這是值得的。 – ZhongYu

+5

恕我直言,這是濫用lambdas。有0個好處,並且使代碼更難閱讀。不要這樣做。 –

4

儘管我希望不是這樣,它背後的理由是,在try-與資源旨在嚴格地必須處理關於該項目的操作。它需要一個命名變量,因爲它希望當你在塊內時你會用這個變量做一些事情。我想這就像編譯器說的:「如果你不打算真正使用這個資源,爲什麼你要用資源嘗試?」

現在你和我完全清楚我們不想真正使用這個資源:我們只是想確保它在我們完成後關閉,所以我們沒有開發人員去鎖定系統。但是像很多事情一樣,他們不得不做出設計決策並佔據少數,我們沒有得到這個功能。

+5

我*使用資源 - 因爲它在'()'和'close()' –

+0

中的副作用,但是你並沒有在塊中使用它,這是try-with-resources的主要用例。我也覺得很沮喪,但事實就是如此。您可以通過'導入靜態'鎖定您的Lock類來節省自己的一些房地產。 – corsiKa

+0

有許多理由不在塊中明確使用資源,例如它可能是鎖;或者保存在一個ThreadLocal中。 –

11

由@McDowell評論的鏈接揭示了由喬達西a blog post comment正確答案誰領導the Java Technology Specification引入的嘗試,與資源聲明:

早在JDK 7,我們開始嘗試-with-resources結構,如 ,它允許使用一般表達式作爲資源, 包括方法調用。然而,由早期 審查 (http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html)草案

「一個可能的發展變化[去嘗試,用資源statemenbt]發現專家組是 對於要指定的資源作爲一般 下探支撐由於允許使用一般表達式作爲資源,所以出現非平凡的規範和實施複雜性 可能是標識符或 PrimaryNoNewArray可能就足夠了,即使更嚴格的 限制只允許一個標識符,所有額外的 實用程序允許一個完整的表達式通過強制聲明 一個新的資源變量)在一個更低的邊際執行和 規範的影響。「

在JDK 7結束時,我們想要的是對資源或現有的最終/有效最終變量的新變量聲明 。我們 只有7次才提供前者;在9,我們也提供 。

+4

java9仍然不支持OP的情況。 – ZhongYu

相關問題