2012-12-12 21 views
14

Próbki z zasobami Java7 są świetne i wszystkie, ale nie mogę sobie wyobrazić, dlaczego wymagane jest zawarcie deklaracji zasobu w oświadczeniu try. Mój gut mówi następujące dokumenty powinny być możliwe:Dlaczego deklaracja jest wymagana w próbie Javy przy próbie zasobu

CloseableResource thing; 
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) { 
    // do some interesting things 
} 
thing.collectSomeStats(); 

Niestety, powoduje to błąd składni (tajemniczo spodziewa się ;). Przenoszenie definicji/deklaracji typu do instrukcji try działa, co oczywiście przenosi rzecz do odpowiedniego zakresu. Mogę wymyślić, jak obejść to, gdy chcę więcej z mojego AutoClosable niż zamykanie, interesuje mnie , dlaczego kompilator wymaga tego w ten sposób.

+1

Od wersji Java 9 wystarczy, jeśli jest to wyrażenie oznaczające odniesienie do ostatecznej lub efektywnej zmiennej końcowej. – aioobe

+0

Aktualizacja JDK - https://bugs.openjdk.java.net/browse/JDK-7196163 –

Odpowiedz

7

Twoja wersja nie jasno określić, jakie powinny być zamknięte, na przykład

CloseableResource thing; 
Parameter a; 

try (a = (thing = methodThatCreatesAThingAndDoesSomeSideEffect()).getParameter()) { 

także co zrobić, jeśli piszesz

try (12) { 

czy coś?

TAKŻE

CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect(); 
CloseableResource thing2 = methodThatCreatesAThingAndDoesSomeSideEffect(); 

try(thing1) { 
} 

dlaczego tylko blisko thing1?

Tak więc obecna składnia wymusza utworzenie jednoczesnej zmiennej z blokiem zamykającym otwarcie.

ALSO2

CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect();

try(thing1) { 
} 

thing1.doSomethingOnClosedResource(); 

od thing1 pozostaje.

+0

Twój pierwszy punkt jest dobry; Odejście od deklaracji otwiera świat funkowych wyrażeń, które w rzeczywistości mogą wywołać wiele niejednoznaczności co do zamknięcia. Drugi to po prostu pebkac, coś Javy próbuje uniknąć zbyt wiele imho. Ale domyślam się, że to tylko osobiste preferencje :) – akaIDIOT

+0

W pierwszym przykładzie A nie jest zamykany, więc nie jest to naprawdę próba z zasobem, drugi przykład, otworzysz tylko rzecz 1, więc zamknie tylko rzecz, don nie widzisz problemu z tym –

+0

@Aviram, co jeśli 'A' jest również' zamykany'? – Dims

2

Czytając specyfikację Java doszedłem do tego wniosku (choć jej nie pośrednio wskazuje tak):

Robią zadeklarować zmienną i dodaje niejawna końcowy do niego, aby upewnić się, że nie można ponownie powiązać zmienną do czegoś jeszcze.

W takim przypadku zamknięcie zasobu nie będzie możliwe, ponieważ nie jest już wiązane z zmienną.

Dla przykładu:

CloseableResource thing; 
try (thing = methodThatCreatesAThingAndDoesSomeSideEffect()) { 
    thing = null; 
    // thing can't be closed now 
} 

Mogli zrobić użyć końcowy, jeśli jej na zewnątrz, ale myślę, że jest to rodzaj brzydki.


Obejście: Można użyć finally jeśli chcesz otrzymać dostęp do deklarowanej zasobu:

try (CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect()) { 
    // do some interesting things 
} finally { 
    thing.collectSomeStats(); 
} 

Pamiętaj, w końcu thing jest już zamknięta

+0

Naprawdę nie jest to odpowiedź na pytanie "dlaczego?", Ale mimo to ważne. – akaIDIOT

+0

Zauważyłem, że po tym, jak przesłałem odpowiedź i zacząłem czytać specyfikacje językowe java, aby sprawdzić, czy wyjaśnią cokolwiek, ale nic na razie. –

+0

Po tym, jak przeczytałem o ukrytym finale, dostałem teorię teraz –

1

Od Java 9 można zadeklaruj i zainicjuj zmienną użytą wewnątrz obiektu try-with-resources poza blokiem. Jedynym dodatkowym wymaganiem dla zmiennej jest to, że musi to być effectively final.
Więc teraz jest to możliwe do zrobienia:

CloseableResource thing = methodThatCreatesAThingAndDoesSomeSideEffect(); 
try (thing) { 
    // do some interesting things 
} 
thing.collectSomeStats(); 

Nadzieję, że to pomaga.

Powiązane problemy