2012-12-12 1 views
14

Le risorse di prova di Java7 sono grandiose e tutte, ma non riesco a capire perché è necessario includere la dichiarazione della risorsa nell'istruzione try. Il mio istinto dice il seguente dovrebbe essere possibile:Perché è richiesta la dichiarazione nella risorsa di prova di Java

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

Ahimè, questo si traduce in un errore di sintassi (cripticamente in attesa di un ;). Lo spostamento della definizione/dichiarazione del tipo nell'istruzione try funziona, il che ovviamente sposta la cosa nello scope corrispondente. Posso capire come ovviare a questo quando desidero di più dal mio AutoClosable che rimanere chiuso, sono interessato a perché il il compilatore lo richiede in questo modo.

+1

A partire da Java 9 è sufficiente se si tratta di un'espressione che indica un riferimento a una variabile finale o effettivamente finale. Aggiornamento – aioobe

+0

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

risposta

7

La versione non definisce in modo chiaro ciò che dovrebbe essere chiuso, ad esempio

CloseableResource thing; 
Parameter a; 

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

anche cosa fare se si scrive

try (12) { 

o qualcosa del genere?

ANCHE

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

try(thing1) { 
} 

perché solo vicino thing1?

Quindi la sintassi corrente impone di creare una variabile simultaneamente con il blocco di apertura.

ALSO2

CloseableResource thing1 = methodThatCreatesAThingAndDoesSomeSideEffect();

try(thing1) { 
} 

thing1.doSomethingOnClosedResource(); 

dal thing1 rimane.

+0

Il tuo primo punto è buono; lasciare la dichiarazione apre un mondo di espressioni funky che potrebbero davvero creare molte ambiguità su cosa chiudere. Il secondo è semplicemente pebkac, qualcosa che Java cerca di evitare un po 'troppo imho. Ma suppongo che sia solo una preferenza personale :) – akaIDIOT

+0

Nel primo esempio, A non è chiudibile quindi non è davvero una risorsa try-with, il secondo esempio, si aprirà solo la cosa 1 in modo che si chiuda solo cosa1, don Si vede un problema con quello –

+0

@Aviram, cosa succede se 'A' è' chiudibile? troppo? – Dims

2

Leggendo la specifica Java sono arrivato a questa conclusione (anche se la sua non indica implicitamente così):

fanno si dichiara la variabile e aggiunge un implicito finale ad esso per assicurarsi che non si può associare nuovamente la variabile a qualcosa altro.

In tal caso sarà impossibile chiudere la risorsa perché non è più associata alla variabile.

Per esempio:

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

potrebbero fare si utilizza finale se fuori ma immagino che è una specie di brutto.


Soluzione: È possibile utilizzare finally se si vuole accedere alla risorsa dichiarato:

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

Tenete a mente finalmente thing è già chiuso

+0

Non proprio una risposta alla domanda * perché *, ma comunque valida. – akaIDIOT

+0

Sì, ho notato che dopo aver inviato la risposta e iniziato a leggere le specifiche java lang per vedere se spiegano qualcosa ma nulla fino a ora –

+0

Dopo aver letto sull'implicito finale ho ottenuto una teoria ora –

1

Dal Java 9 è possibile dichiarare e inizializzare la variabile utilizzata all'interno di try-with-resources all'esterno del blocco. L'unico requisito aggiuntivo per la variabile è che deve essere effectively final.
Così ora è possibile fare:

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

Speranza che aiuta.