T
- typ elementu kolekcepublic final class AutoCloseables<T extends java.lang.AutoCloseable>
extends java.lang.Object
implements java.lang.AutoCloseable
AutoCloseable
. Kolekce samotná
implementuje toto rozhraní také. Při
zavírání kolekce se rozvněž zavřou všechny
elementy. Elementem může být i kolekce, takže lze snadno vytvořit
hierarchickou strukturu.
Primárním účelem této kolekce je zajištění uzavření objektů, které zapomněl provést programátor-uživatel těchto objektů. V normální situaci programátor postupuje tak, že nebezpečný kód uzavře do try-catch-finally nebo try-with-resources bloku:
// try-catch-finally
AutoCloseable tcf = new ...;
try {
...
} finally {
tcf.close();
}
// try-with-resources
try (AutoCloseable twr = new ...) {
...
}
V takovém případě je vše v pořádku. Ale programátor je tvor zapomnětlivý, při
nezavření může objekt blokovat nějaký prostředek, v klient-serverové aplikaci
dokonce i po svém ukončení. Programátor-tvůrce objektu tak má nelehký úkol
uvolnit prostředky, jakmile nejsou potřeba. A ty nejsou určitě ve chvíli, kdy
zmizí poslední reference na objekt a
carbage collector se rozhodne objekt zfinalizovat.
Tak nezbývá, než zavření svěřit metodě Object.finalize()
. Jenže ani
to není stoprocentní, při ukončení aplikace se objekty nefinalizují.
A tak nastává čas pro AutoCloseables
. Následuje vzorové použití:
public class SafeObject implements AutoCloseable {
private static final AutoCloseables<SafeObject> CLOSE = AutoCloseables.create();
public SafeObject() {
...
CLOSE.register(this);
}
@Override
protected void finalize() {
close();
super.finalize();
}
@Override
public void close() {
CLOSE.unregister(this);
...
}
}
Při dodržení tohoto návrhové vzoru je vysoce provaděpodobné, že objekt, jehož
včasné a řádné zavření nám leží na srdci, se hned po svém vytvoření zařadí do
registru (pozor na přetížené konstruktory, musí se registrovat v každém a měl
by jen jednou), pak žije a dělá něco užitečného, pokud je
programátor-uživatel spolehlivý, hned po použití je objekt uzavřen, tedy
vyřazen z registru, pak se zruší jeho reference, dojde k finalizaci a druhému
uzavření (což by měl finalizátor zvládnout, i kdyby byla vyvolána výjimka) a
druhému vyřazení z registru (což registr zvládne).
Při opomenutí uzavření buď GC rozhodne o vyřazení objektu a zavolá finalizaci, které následně zavolá první zavření a první vyřazení, nebo aplikace skončí bez finalizace, tak nastupuje naše kolekce, která si ukončení aplikace hlídá, pokud tou dobou jsou v kolekci zbylé (nezavřené a nevyřazené) objekty, zavře a vyřadí je sama, teprve až nebude mít žádnou referenci otevřenou, dovolí aplikaci její ukončení.
Modifier and Type | Method and Description |
---|---|
void |
close()
Zavře sebe a všechny držené elementy.
|
static <T extends java.lang.AutoCloseable> |
create()
Vytvoří samozavírací kolekci bez rodiče, tedy na nejvyšší úrovni.
|
static <T extends java.lang.AutoCloseable> |
create(AutoCloseables<AutoCloseables> parent)
Vytvoří samozavírací kolekci s rodičem.
|
T |
register(T obj)
Registruje objekt do kolekce.
|
boolean |
unregister(T obj)
Odregistruje objekt z kolekce.
|
public static <T extends java.lang.AutoCloseable> AutoCloseables<T> create()
T
- typ elementu, který bude kolekce držet, typicky třída, ve
které se ochrana před zapomenutým zavřením tvořípublic static <T extends java.lang.AutoCloseable> AutoCloseables<T> create(AutoCloseables<AutoCloseables> parent)
T
- typ elementu, který bude kolekce držet, typicky třída, ve
které se ochrana před zapomenutým zavřením tvoříparent
- rodičovská kolekce pro hierarchické uspořádání (uzavřením
rodiče se také zavřou všechny sesterské objekty)public T register(T obj) throws java.lang.IllegalStateException
obj
- registrovaný objektjava.lang.IllegalStateException
- pokud registrace probíhá v okamžiku, kdy už
je kolekce uzavřenapublic boolean unregister(T obj)
obj
- odregistrovávaný objekttrue
, pokud se podařilo objekt najít odstranit (ne
zavřít)public void close()
close
in interface java.lang.AutoCloseable