Java - Essayez avec des ressources

1. Vue d'ensemble

La prise en charge de try-with-resources - introduite dans Java 7 - nous permet de déclarer les ressources à utiliser dans un bloc try avec l'assurance que les ressources seront fermées après l'exécution de ce bloc.

Les ressources déclarées doivent implémenter l' interface AutoCloseable .

2. Utilisation de try-with-resources

En termes simples, pour être fermée automatiquement, une ressource doit être à la fois déclarée et initialisée à l'intérieur de l' essai , comme indiqué ci-dessous:

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) { writer.println("Hello World"); } 

3. Remplacement de try - catch-finally par try-with-resources

Le moyen simple et évident d'utiliser la nouvelle fonctionnalité try-with-resources est de remplacer le bloc try-catch-finally traditionnel et détaillé .

Comparons les exemples de code suivants - tout d'abord est un bloc try-catch-finally typique , puis la nouvelle approche, en utilisant un bloc try-with-resources équivalent:

Scanner scanner = null; try { scanner = new Scanner(new File("test.txt")); while (scanner.hasNext()) { System.out.println(scanner.nextLine()); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (scanner != null) { scanner.close(); } }

Et voici la solution super succincte utilisant try-with-resources:

try (Scanner scanner = new Scanner(new File("test.txt"))) { while (scanner.hasNext()) { System.out.println(scanner.nextLine()); } } catch (FileNotFoundException fnfe) { fnfe.printStackTrace(); }

Voici où vous pouvez explorer davantage la classe Scanner .

4. essayez avec des ressources avec plusieurs ressources

Plusieurs ressources peuvent être déclarées très bien dans un bloc try-with-resources en les séparant par un point-virgule:

try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { while (scanner.hasNext()) { writer.print(scanner.nextLine()); } }

5. Une ressource personnalisée avec fermeture automatique

Pour construire une ressource personnalisée qui sera correctement gérée par un bloc try-with-resources , la classe doit implémenter les interfaces Closeable ou AutoCloseable et remplacer la méthode close :

public class MyResource implements AutoCloseable { @Override public void close() throws Exception { System.out.println("Closed MyResource"); } }

6. Ordre de clôture des ressources

Les ressources qui ont été définies / acquises en premier seront fermées en dernier; regardons un exemple de ce comportement:

Ressource 1:

public class AutoCloseableResourcesFirst implements AutoCloseable { public AutoCloseableResourcesFirst() { System.out.println("Constructor -> AutoCloseableResources_First"); } public void doSomething() { System.out.println("Something -> AutoCloseableResources_First"); } @Override public void close() throws Exception { System.out.println("Closed AutoCloseableResources_First"); } } 

Ressource 2:

public class AutoCloseableResourcesSecond implements AutoCloseable { public AutoCloseableResourcesSecond() { System.out.println("Constructor -> AutoCloseableResources_Second"); } public void doSomething() { System.out.println("Something -> AutoCloseableResources_Second"); } @Override public void close() throws Exception { System.out.println("Closed AutoCloseableResources_Second"); } }

Code:

private void orderOfClosingResources() throws Exception { try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst(); AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) { af.doSomething(); as.doSomething(); } } 

Production:

Constructeur -> AutoCloseableResources_First

Constructeur -> AutoCloseableResources_Second

Quelque chose -> AutoCloseableResources_First

Quelque chose -> AutoCloseableResources_Second

Fermé AutoCloseableResources_Second

Fermé AutoCloseableResources_First

7. attraper et enfin

Un bloc try-with-resources peut toujours avoir les blocs catch et finally - qui fonctionneront de la même manière qu'avec un bloc try traditionnel .

8. Java 9: ​​effectivement finalVariables

Avant Java 9, nous ne pouvions utiliser de nouvelles variables que dans un bloc try-with-resources :

try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { // omitted }

Comme indiqué ci-dessus, cela était particulièrement détaillé lors de la déclaration de plusieurs ressources. À partir de Java 9 et dans le cadre de JEP 213, nous pouvons désormais utiliser des variables finales ou même effectivement finales dans un bloc try-with-resources :

final Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt")) try (scanner;writer) { // omitted }

En termes simples, une variable est effectivement définitive si elle ne change pas après la première affectation, même si elle n'est pas explicitement marquée comme finale .

Comme indiqué ci-dessus, la variable scanner est déclarée finale explicitement, nous pouvons donc l'utiliser avec le bloc try-with-resources . Bien que la variable d' écriture ne soit pas explicitement finale, elle ne change pas après la première affectation. Par conséquent, nous sommes également autorisés à utiliser la variable writer .

9. Conclusion

Dans cet article, nous avons expliqué comment utiliser try-with-resources, comment remplacer try , catch et enfin try-with-resources, créer des ressources personnalisées avec AutoCloseable et l'ordre dans lequel les ressources sont fermées.

Le code source complet de l'exemple est disponible dans ce projet GitHub.