REPL réalisé avec Java8, c'est le troisième. Comme l'article précédent pèse plus que prévu, nous allons cette fois créer un objet plus léger.
Après avoir utilisé Java pour la première fois depuis longtemps, la première chose qui m'a surpris a été l'absence de destructeur. Lorsque je veux implémenter le soi-disant ** RAII (l'acquisition de ressources est l'initialisation) **, comment puis-je l'implémenter sans destructeur? est devenu. Par conséquent, cette fois, nous allons créer une classe pour réaliser l'acquisition / libération de ressources à utiliser dans REPL et autres.
Je ne sais pas très bien comment implémenter la libération des ressources en Java, je vais donc le résumer en gros.
Object.finalize()En remplaçant la méthode, vous pouvez écrire un traitement de publication arbitraire au moment de la récupération de place.
Cependant, la méthode finalize () est exécutée lorsque l'objet est détruit par le garbage collector, nous ne savons donc pas quand il sera exécuté. Surtout dans l'environnement PC actuel où la mémoire est abondante, elle peut ne pas être appelée tant que l'application n'est pas fermée.
Pour les ressources qui ne peuvent être utilisées que dans l'application et ne peuvent être réutilisées qu'après le processus de publication (je ne pouvais pas penser à un exemple), il n'y a aucune garantie que le processus de publication fonctionnera avant la réutilisation, utilisez cette méthode. ne peux pas.
AutoCloseable.close()
En créant une classe d'implémentation d'interface AutoCloseable et en utilisant le bloc try-with-resource, la méthode close () implémentée est automatiquement appelée à la fin du bloc try.
Ce format est généralement recommandé, mais il doit être utilisé dans une seule méthode, il ne peut donc pas être utilisé, par exemple, si vous souhaitez détruire un objet de composition lorsque l'objet parent est détruit. Il existe également un moyen d'appeler close () de l'objet de composition par vous-même, mais est-ce l'utilisation d'origine? Je doute si demandé.
#### **`python`**
```java
try ( InputStreamReader in = new InputStreamReader(filepath) ) {
char c = in.read(); //Traitement utilisant dans
method(in); //Il est possible de passer via la méthode en chemin
// ..Autre traitement
} //Où est automatiquement libéré
Par conséquent, nous allons implémenter la classe Finalizer qui libère les objets enregistrés.
C'est une interface à implémenter dans la classe dont vous souhaitez terminer le traitement. C'est un mécanisme qui oblige Finlizer à contenir une collection de Finalizable et appelle cleanup () des objets de la collection séquentiellement à la fin.
Interface.java
package console;
interface Interface {
interface Finalizable {
void cleanup();
}
}
Il s'agit du conteneur de la classe d'implémentation Finalizable et de la classe de contrat de traitement de résiliation.
python
package console;
final class Finalizer {
/**Enregistrement de classe d'implémentation finalisable. */
final void register(Interface.Finalizable f) {
if ( finalizers_.contains(f) ) { return; }
finalizers_.add(0, f); // push front
}
final void remove(Interface.Finalizable f) {
if ( !finalizers_.contains(f) ) { return; }
finalizers_.remove(f);
}
/**Enregistré Finalisable.cleanup()Pour appeler et supprimer dans l'ordre inverse de l'inscription. */
final void cleanup() {
for ( Interface.Finalizable f: finalizers_ ) {
try {
f.cleanup();
} catch(java.lang.RuntimeException e) {
System.err.println( e.getMessage() );
}
}
finalizers_.clear();
finalizers_ = null;
}
private java.util.List<Interface.Finalizable> finalizers_ = new java.util.ArrayList<>();
}
Register (Finalizable)
```Une méthode pour enregistrer la classe d'implémentation Finalizable. `remove ()`
`Une méthode pour supprimer la classe d'implémentation Finalizable enregistrée.cleanup ()
`Appelez cleanup () des objets dans le conteneur dans l'ordre. Si vous souhaitez libérer des ressources et que Hoge est nécessaire pour initialiser Foo, enregistrez-le dans Finlaizer dans l'ordre Hoge → Foo. En faisant cela, Hoge ne sera pas publié avant Foo, donc même si vous utilisez Foo dans Hoge.cleanup (), il n'y aura pas de problème. Cependant, sauf si vous appelez manuellement Foo.cleanup () ...
【Exemple d'utilisation】
Finalizer fin = new Finalizer();
Hoge h = new Hoge();
fin.register(h);
Foo f = new Foo(h);
fin.register(f);
// ... Hoge,Traitement à l'aide de Foo
fin.cleanup()
Finalizer.cleanup () doit être appelé par lui-même lors de la destruction d'un objet, mais si vous l'enregistrez ici, il libèrera les ressources d'un seul coup, donc si vous l'implémentez correctement, vous pouvez résoudre considérablement le problème des fuites de ressources. pense. La méthode cleanup () portant le même nom que la méthode de la classe Finalizer est enregistrée en tant que classe abstraite dans la partie 1 de la classe BaseREPL. Lorsque vous utilisez Finalizer dans une classe dérivée, vous pouvez appeler la méthode Finalizer.cleanup () à partir de cette méthode pour vous assurer que le processus de libération des ressources enregistré juste avant la fin de la méthode BaseREPL.run () est exécuté. Je vais.
Exemple d'implémentation dans REPL
class XxxxREPL extends BaseREPL {
XxxxREPL(String encoding) {
super(encoding);
obj1 = new Object1();
finalizer.register(obj1);
finalizer.register(obj2);
}
protected void cleanup() {
finalizer.cleanup(): //nettoyage dans l'ordre obj2, obj1()Est appelé
}
private Finalizer finalizer = new Finalizer();
private Object1 /* implements Finalizable */ obj1;
private Object2 /* implements Finalizable */ obj2 = new Object2();
}
Recommended Posts