Pourquoi try-with-resource requirejs-il une variable locale?

En référence à ma question Tout risque dans un wrapper AutoCloseable pour java.util.concurrent.locks.Lock? Je me demande pourquoi trh try-with-resource requirejs une variable locale nommée .

Mon utilisation actuelle est la suivante:

 try (AutoCloseableReentrantReadWiteLock.Lock l = _lock.writeLock()) { // do something } 

La variable l n’est pas utilisée dans le bloc try et ne pollue que l’espace de noms. D’après ce dont je me souviens, l’instruction C# using analogue ne nécessite pas de variable nommée locale.

Y a-t-il une raison pour laquelle les éléments suivants n’ont pas pu être pris en charge, avec une variable locale anonyme fermée à la fin du bloc try?

 try (_lock.writeLock()) { // do something } 

Le lien dans le commentaire de @McDowell révèle la réponse correcte dans un commentaire de blog de Joe Darcy qui a dirigé la spécification de la technologie Java qui a introduit la déclaration try-with-resources:

De retour dans JDK 7, nous avons commencé avec une construction try-with-resources qui permettait d’utiliser une expression générale pour la ressource, y compris un appel de méthode. Cependant, le groupe d’experts a constaté lors de l’examen préliminaire du projet ( http://jcp.org/aboutJava/communityprocess/edr/jsr334/index.html ) que

“Un éventuel changement futur [de la ressource try-with-resources] supprime la prise en charge d’une ressource à spécifier en tant qu’expression générale. Une spécification complexe et une implication complexe résultent de l’utilisation d’une expression générale comme ressource. pourrait être un identifiant ou un PrimaryNoNewArray pourrait suffire Même la ressortingction la plus sévère de n’autoriser qu’un identifiant peut fournir presque tout l’utilité supplémentaire de permettre une expression complète (en forçant la déclaration d’une nouvelle variable de ressource) à une implémentation marginale beaucoup plus faible impact des spécifications. ”

À la fin du JDK 7, nous voulions une nouvelle déclaration de variable pour la ressource ou une variable finale finale / effective existante. Nous n’avons eu que le temps de fournir à l’ancien en 7; en 9, nous fournissons également ce dernier.

Parmi les cas d’utilisation qu’ils envisageaient, la plupart auraient besoin d’accéder à la ressource à l’intérieur du bloc, par exemple, ouvrir le fichier – lecture / écriture de fichier – fermer le fichier. Ils n’auraient pas pris cette décision de conception s’ils pensaient qu’il y avait beaucoup de cas d’utilisation où la variable locale n’était pas utilisée.

Quant à savoir pourquoi Lock n’est pas auto-fermable, je pense que Doug Lea n’est pas trop concerné par la syntaxe, il se concentre sur la résolution du problème difficile. D’autres peuvent toujours append du sucre syntaxique en plus de ses utilitaires.

À plus long terme, les essais avec ressources tomberont probablement à la mode, remplacés par lambda. Par exemple

 lock.withLock( ()->{ execute-while-holding-the-lock; } ); 

Bien que ce ne soit pas le cas, la raison en est que l’essai avec ressources est ssortingctement destiné aux opérations sur l’object à éliminer. Il nécessite une variable nommée car elle attend que vous fassiez quelque chose avec cette variable lorsque vous êtes dans le bloc. Je suppose que c’est comme si le compilateur disait “Si vous ne prévoyez pas d’utiliser la ressource, pourquoi faites-vous un essai avec les ressources?”

Maintenant, vous et moi soaps très bien que nous ne voulons pas réellement utiliser la ressource: nous voulons simplement nous assurer qu’elle est fermée lorsque nous en aurons fini, afin que les développeurs ne bloquent pas le système. Mais comme tant de choses, ils devaient prendre des décisions en matière de conception et être en minorité, nous n’avons pas eu la fonctionnalité.

Je pense que l’incapacité à utiliser une variable locale était le déclencheur de try-with-resource.

Avant java 1.7, vous deviez écrire quelque chose comme ceci:

 InputStream in = null; try { in = ....; } finally { if (in != null) { in.close(); } } 

Il y a 2 inconvénients ici:

  1. bloc finally est ennuyeux et doit être null-safe pour chaque ressource de fermeture
  2. Nous devons déclarer les ressources en dehors du bloc simplement pouvoir y accéder en bloc finally . Par conséquent, nous élargissons la scope où les variables sont accessibles, ce qui est une mauvaise pratique.

La syntaxe try-with-resource résout les deux problèmes:

  1. finally bloc n’est pas du tout nécessaire.
  2. La variable de ressource rest accessible dans le bloc try uniquement, c’est-à-dire là où elle doit être connue.

C’est pourquoi la ressource pouvant être fermée doit être locale. Sinon, l’un des principaux inconvénients de la syntaxe try-with-resource est “disabled”.