2008-09-26 7 views

Répondre

21

Oui. Java 1.7 a introduit la construction try-with-resources vous permettant d'écrire:

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

... comme une déclaration using.

Malheureusement, avant Java 1.7, les programmeurs Java étaient obligés d'utiliser try {...} enfin {...}. En 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

Est-il possible de mettre à jour cette réponse avec un exemple de C# avec son bloc using, puis Java avec un try-finally? De préférence un exemple qui utilise deux ressources distinctes afin que nous puissions documenter comment nous assurer que tout est fermé correctement. –

+2

En tant que gars Java, la comparaison ci-dessus est juste un peu douloureux. –

+0

Bien que techniquement correct, ce modèle try/finally n'est pas le meilleur. Utilisez: X x = new X(); essayez {/ * work * /} enfin {x.disposer(); } – McDowell

2

Pas que je sache. Vous pouvez simuler un peu avec un try ... finally block, mais ce n'est toujours pas pareil.

-3

Non, il n'y a pas d'utilisation en Java, la fonctionnalité la plus similaire est le mot clé "import".

+0

L'affiche originale ne faisait pas référence à comprend. Voir http://msdn.microsoft.com/en-us/library/yh598w02(VS.80).aspx – McDowell

+3

Mauvais @shifoz! Vous êtes cruels. La question était totalement vague et il aurait pu vouloir dire ceci: http://msdn.microsoft.com/en-us/library/sf0df423 (VS.80) .aspx ... Shifoz, vous pouvez récupérer quelques points en posant des questions sur les programmeurs aiment "quelle est votre couleur de programmation de favori en RVB?" –

-2

Non, il n'y en a pas.

Vous pouvez

public void func(){ 

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

} 

Cela vous donne la portée limitée de la clause à l'aide, mais il n'y a pas d'interface IDisposable pour appeler le code de finalisation. Vous pouvez utiliser try {} catch() {} Finally {}, mais il n'a pas le sucre d'utiliser. Incidemment, l'utilisation de finaliseurs en Java est généralement une mauvaise idée.

1

Je pense que vous pouvez réaliser quelque chose de similaire au bloc "using", en implémentant une classe interne anonyme. Comme le fait le printemps avec les "modèles Dao".

2

Le plus proche que vous pouvez obtenir en Java est try/finally. En outre, Java ne fournit pas de type jetable implicite.

C#: la portée de la variable en dehors d'un aide de bloc

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: la portée de la variable en dehors d'un bloc

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#: la portée de la variable dans un bloc

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: la portée de la variable dans un bloc

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

Eh bien, en utilisant du sucre syntaxique était de toute façon si Java semblables, ne transpirent pas.

5

L'équivalent le plus proche dans la langue est d'utiliser try-finally.

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

devient

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

Notez la forme générale est toujours:

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

Si l'acquisition est dans le bloc d'essai, vous publierons dans le cas où l'acquisition échoue. Dans certains cas, vous pourriez être en mesure de pirater avec du code inutile (typiquement tester null dans l'exemple ci-dessus), mais dans le cas de, disons, ReentrantLock mauvaises choses vont se passer.

Si vous faites souvent la même chose, vous pouvez utiliser l'idiome "execute around". Malheureusement, la syntaxe de Java est verbeuse, donc il y a beaucoup de plaque de Bolier.

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

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

exemple plus compliqué mon, par exemple, enveloppez exceptions.

0

Si nous obtenons des fermetures BGGA en Java, cela ouvrirait aussi des structures similaires en Java. Gafter a utilisé cet exemple dans ses diapositives, par exemple:

withLock(lock) { //closure } 
0

L'idiome réel utilisé par la plupart des programmeurs pour le premier exemple est la suivante:

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

Il y a moins indentation en utilisant cet idiome, qui devient encore plus important lorsque vous avez plus de 2 ressources à nettoyer.

De plus, vous pouvez ajouter une clause catch à la structure qui va traiter les nouvelles FileStream() en lançant une exception si vous en avez besoin. Dans le premier exemple, vous devriez avoir un autre bloc essay/catch si vous vouliez le faire.

+0

Ce code ne ferme pas is2 si l'appel à is1.close() renvoie une exception. Le code imbriqué donné dans la question est préférable. – cunkel

9

Oui, depuis Java 7, vous pouvez réécrire:

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

Comme

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

Les objets transmis en tant que paramètres à l'instruction try devrait mettre en œuvre java.lang.AutoCloseable .Have un regard sur le official docs.

Pour les versions plus anciennes de Java, passez la commande this answer et this answer.