2008-09-26 13 views

risposta

21

Sì. Java 1.7 ha introdotto il costrutto try-with-resources consente di scrivere:

try(InputStream is1 = new FileInputStream("/tmp/foo"); 
    InputStream is2 = new FileInputStream("/tmp/bar")) { 
     /* do stuff with is1 and is2 */ 
} 

... proprio come una dichiarazione using.

Sfortunatamente, prima di Java 1.7, i programmatori Java erano costretti a utilizzare try {...} finally {...}. In Java 1.6:

InputStream is1 = new FileInputStream("/tmp/foo"); 
try{ 

    InputStream is2 = new FileInputStream("/tmp/bar"); 
    try{ 
     /* do stuff with is1 and is 2 */ 

    } finally { 
     is2.close(); 
    } 
} finally { 
    is1.close(); 
} 
+0

È possibile aggiornare questa risposta con un esempio di C# con il suo blocco using, quindi Java con un try-finally? Preferibilmente un esempio che utilizza 2 risorse separate in modo che possiamo documentare come assicurarsi che tutto sia chiuso correttamente. –

+2

Come un ragazzo di Java, il confronto sopra è solo un po 'doloroso. –

+0

Sebbene tecnicamente corretto, questo pattern try/finally non è il migliore. Usa: X x = new X(); prova {/ * work * /} finally {x.dispose(); } – McDowell

2

Non che io sia a conoscenza. Puoi in qualche modo simulare con un tentativo ... infine bloccare, ma non è ancora lo stesso.

-3

No, non viene utilizzato in Java, la funzionalità più simile è la parola chiave "importa".

+0

Il poster originale non si riferiva a include. Vedi http://msdn.microsoft.com/en-us/library/yh598w02(VS.80).aspx – McDowell

+3

Povero @shifoz! Voi ragazzi siete crudeli. La domanda era totalmente vaga e avrebbe potuto intendere questo http://msdn.microsoft.com/en-us/library/sf0df423 (VS.80) .aspx ... Shifoz, puoi recuperare alcuni punti chiedendo qualcosa a proposito programmatori come "qual è il tuo colore di programmazione preferito in RGB?" –

-2

No, non c'è.

Puoi

public void func(){ 

    { 
    ArrayList l = new ArrayList(); 
    } 
    System.out.println("Hello"); 

} 

Questo vi dà la portata limitata della clausola di utilizzare, ma non v'è alcuna interfaccia IDisposable di chiamare il codice di finalizzazione. Puoi usare try {} catch() {} Finally {}, ma non ha lo zucchero da usare. Tra l'altro l'utilizzo di finalizzatori in Java è generalmente una cattiva idea.

1

Penso che si possa ottenere qualcosa di simile al blocco "using", implementando una classe interna anonima. Come la primavera fa con i "modelli di Dao".

2

Il più vicino che è possibile ottenere in Java è provare/finalmente. Inoltre, Java non fornisce un tipo Disposable implicito.

C#: scoping la variabile all'esterno di un utilizzando blocco

public class X : System.IDisposable { 

    public void Dispose() { 
     System.Console.WriteLine("dispose"); 
    } 

    private static void Demo() { 
     X x = new X(); 
     using(x) { 
      int i = 1; 
      i = i/0; 
     } 
    } 

    public static void Main(System.String[] args) { 
     try { 
      Demo(); 
     } catch (System.DivideByZeroException) {} 
    } 

} 

Java: scoping la variabile all'esterno di un blocco

public class X { 

    public void dispose() { 
     System.out.println("dispose"); 
    } 

    private static void demo() { 
     X x = new X(); 
     try { 
      int i = 1/0; 
     } finally { 
      x.dispose(); 
     }   
    } 

    public static void main(String[] args) { 
     try { 
      demo(); 
     } catch(ArithmeticException e) {} 
    } 

} 

C#: scoping la variabile all'interno di un blocco

public class X : System.IDisposable { 

    public void Dispose() { 
     System.Console.WriteLine("dispose"); 
    } 

    private static void Demo() { 
     using(X x = new X()) { 
      int i = 1; 
      i = i/0; 
     } 
    } 

    public static void Main(System.String[] args) { 
     try { 
      Demo(); 
     } catch (System.DivideByZeroException) {} 
    } 

} 

Java: scoping la variabile all'interno di un blocco

public class X { 

    public void dispose() { 
     System.out.println("dispose"); 
    } 

    private static void demo() { 
     { 
      X x = new X(); 
      try { 
       int i = 1/0; 
      } finally { 
       x.dispose(); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     try { 
      demo(); 
     } catch(ArithmeticException e) {} 
    } 

} 
0

Bene, usando era zucchero sintattico comunque così compagni di Java, non preoccupatevi.

5

L'equivalente più vicino nella lingua è utilizzare try-finally.

using (InputStream in as FileInputStream("myfile")) { 
    ... use in ... 
} 

diventa

final InputStream in = FileInputStream("myfile"); 
try { 
    ... use in ... 
} finally { 
    in.close(); 
} 

Nota la forma generale è sempre:

acquire; 
try { 
    use; 
} finally { 
    release; 
} 

Se l'acquisizione è all'interno del blocco try, si rilascerà nel caso che l'acquisizione non riesce. In alcuni casi potresti essere in grado di hackerare con codice non necessario (tipicamente testando null nell'esempio sopra), ma nel caso, ad esempio, di ReentrantLock accadranno cose brutte.

Se si sta facendo spesso la stessa cosa, è possibile utilizzare l'espressione "Esegui intorno". Sfortunatamente la sintassi di Java è prolissa, quindi c'è un sacco di bolier plate.

fileInput("myfile", new FileInput<Void>() { 
    public Void read(InputStream in) throws IOException { 
     ... use in ... 
     return null; 
    } 
}); 

dove

public static <T> T fileInput(FileInput<T> handler) throws IOException { 
    final InputStream in = FileInputStream("myfile"); 
    try { 
     handler.read(in); 
    } finally { 
     in.close(); 
    } 
} 

esempio più complicato il mio, per esempio, avvolgere eccezioni.

0

Se otteniamo chiusure BGGA in Java, questo si aprirà anche per strutture simili in Java. GDopo ha utilizzato questo esempio nelle sue diapositive, ad esempio:

withLock(lock) { //closure } 
0

L'idioma reale utilizzato dalla maggior parte dei programmatori per il primo esempio è questo:

InputStream is1 = null; 
InputStream is2 = null; 
try{ 
    is1 = new FileInputStream("/tmp/bar"); 
    is2 = new FileInputStream("/tmp/foo"); 

    /* do stuff with is1 and is 2 */ 

} finally { 
    if (is1 != null) { 
     is1.close(); 
    } 
    if (is2 != null) { 
     is2.close(); 
    } 
} 

c'è meno il rientro di utilizzare questo linguaggio, che diventa ancora più importante quando hai più di 2 risorse da ripulire.

Inoltre, è possibile aggiungere una clausola di catch alla struttura che gestirà il nuovo FileStream() generando un'eccezione se necessario. Nel primo esempio dovresti avere un altro blocco try/catch che racchiudi se vuoi farlo.

+0

Questo codice non riesce a chiudere is2 se la chiamata a is1.close() genera un'eccezione. Il codice annidato indicato nella domanda è preferibile. – cunkel

9

Sì, dal momento che Java 7 è possibile riscrivere:

InputStream is1 = new FileInputStream("/tmp/foo"); 
try{ 

    InputStream is2 = new FileInputStream("/tmp/bar"); 
    try{ 
     /* do stuff with is1 and is2 */ 

    } finally { 
     is2.close(); 
    } 
} finally { 
    is1.close(); 
} 

Come

try(InputStream is1 = new FileInputStream("/tmp/foo"); 
    InputStream is2 = new FileInputStream("/tmp/bar")) { 
     /* do stuff with is1 and is2 */ 
} 

Gli oggetti passati come parametri per l'istruzione try dovrebbe implementare java.lang.AutoCloseable Abbia uno sguardo alla official docs.

Per versioni precedenti di Java checkout this answer e this answer.

Problemi correlati