2008-09-26 7 views

Antwort

21

Ja. 1.7 Java eingeführt, um die try-with-resources Konstrukt Sie zu schreiben erlaubt:

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

... wie ein using Aussage.

Leider waren Java-Programmierer vor Java 1.7 gezwungen, try {...} finally {...} zu verwenden. 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

Ist es möglich, diese Antwort mit einem Beispiel von C# mit seinem using Block zu aktualisieren, dann Java mit einem try-finally? Vorzugsweise ein Beispiel, das zwei separate Ressourcen verwendet, so dass wir dokumentieren können, wie sichergestellt wird, dass alles ordnungsgemäß geschlossen wird. –

+2

Als Java-Typ ist der obige Vergleich nur ein bisschen schmerzhaft. –

+0

Obwohl technisch korrekt, ist dieses try/finally-Muster nicht das beste. Verwenden Sie: X x = neues X(); versuch {/ * work * /} endlich {x.entsorgen(); } – McDowell

2

Nicht, dass ich bewusst bin. Sie können etwas mit einem Versuch simulieren ... endlich blockieren, aber es ist immer noch nicht ganz dasselbe.

-3

Nein, es gibt keine Verwendung in Java, die ähnlichste Funktionalität ist das Schlüsselwort "import".

+0

Das ursprüngliche Plakat bezog sich nicht auf enthält. Siehe http://msdn.microsoft.com/en-us/library/yh598w02(VS.80).aspx – McDowell

+3

Poor @shifoz! Ihr seid grausam. Die Frage war völlig vage und er könnte das gemeint haben http://msdn.microsoft.com/en-us/library/sf0df423 (VS.80) .aspx ... Shifoz, Sie können einige Punkte wiederherstellen, indem Sie etwas fragen Programmierer mögen "was ist Ihre Lieblings-Programmierfarbe in RGB?" –

-2

Nein, gibt es nicht.

Sie können

public void func(){ 

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

} 

Dies gibt Ihnen den begrenzten Umfang der using-Klausel, aber es gibt keinen IDisposable-Schnittstelle Finalisierungscode zu nennen. Sie können versuchen {} catch() {} Endlich {}, aber es hat nicht den Zucker zu verwenden. Übrigens ist die Verwendung von Finalizern in Java generell eine schlechte Idee.

1

Ich denke, Sie können etwas erreichen, das dem "using" -Block ähnelt und eine anonyme innere Klasse implementiert. Wie Spring mit den "Dao Templates".

2

Das nächste, was Sie in Java bekommen können, ist versuchen/endlich. Außerdem bietet Java keinen impliziten Disposable-Typ.

C#: Scoping die Variable außerhalb eines unter Verwendung von Block

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 die Variable außerhalb eines Blocks

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 die Variable innerhalb eines Blocks

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 die Variable innerhalb eines Blocks

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

Nun, unter Verwendung war syntaktischer Zucker sowieso so Java Fellows, nicht schwitzen sie.

5

Das nächste Äquivalent in der Sprache ist try-finally.

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

wird

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

Beachten Sie die allgemeine Form ist immer:

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

Wenn Erwerb innerhalb des Try-Block ist, können Sie in dem Fall freigeben wird, dass der Erwerb fehlschlägt. In einigen Fällen können Sie möglicherweise mit unnötigem Code herumhacken (normalerweise im obigen Beispiel auf Null testen), aber im Fall von, sagen wir, ReentrantLock werden schlimme Dinge passieren.

Wenn Sie häufig dasselbe tun, können Sie das Idiom "execute around" verwenden. Leider ist die Syntax von Java sehr ausführlich, es gibt also eine Menge bolerier Platte.

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

wo

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

Kompliziertere Beispiel meine, zum Beispiel Ausnahmen wickeln.

0

Wenn wir BGGA-Closures in Java bekommen, würde dies auch für ähnliche Strukturen in Java öffnen. Gafter hat dieses Beispiel in seinen Folien verwendet, zum Beispiel:

withLock(lock) { //closure } 
0

Das eigentliche Idiom von den meisten Programmierern für das erste Beispiel verwendet wird, ist dies:

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(); 
    } 
} 

Es ist weniger Einrücken dieses Idiom mit, das wird noch wichtiger, wenn Sie mehr als 2 Ressourcen zum Bereinigen haben.

Sie können der Struktur auch eine catch-Klausel hinzufügen, die sich mit der neuen Datei FileStream() befasst, die eine Ausnahme auslöst, wenn Sie sie benötigen. Im ersten Beispiel müssten Sie einen anderen umschließenden try/catch-Block haben, wenn Sie dies tun wollten.

+0

Dieser Code kann Is2 nicht schließen, wenn der Aufruf von is1.close() eine Ausnahme auslöst. Der in der Frage angegebene geschachtelte Code ist vorzuziehen. – cunkel

9

Ja, da Java 7 können Sie umschreiben:

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(); 
} 

Als

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

Die Objekte als Parameter an die try-Anweisung übergeben sollte java.lang.AutoCloseable .Have einen Blick auf die official docs implementieren.

Für ältere Versionen von Java checkout this answer und this answer.

Verwandte Themen