Ket kriterium van:
1. Ne kelljen expliciten hivogatni a close()-t mert az hibaforras (el lehet felejteni). Tortenjen meg automatikusan, amikor mar nem kell az eroforras.
2. Az automatizmus determinisztikus kell, hogy legyen, tehat a close() meghivasa nem lehet a gc resze, hiszen nem alapozhatsz ra, hogy a gc mikor tortenik meg.
Erre van ugye a scope based resource management:
void foo() {
try (Socket s = new Socket()) {
}
}
Itt megvan az a garanciad, hogy amint elhagyod a try scope-ot, az s.close() meghivasra kerul, fuggetlenul a gc-tol.
Ennek a megoldasnak az a problemaja, hogy maga a try-with-resource egy explicit keres, amit szinten el lehet felejteni. Mondjuk azert mert a Socket osztaly egy korabbi iteracioban meg nem volt Closeable (kicsit eroltetett a pelda de van realitasa mas kontextusban).
pl. ha ezt csinalod:
void foo() {
try {
Socket s = new Socket();
} finally {
// ...
}
}
Es a finally-ban elfelejted a socketet zarni, akkor megszivtad, marad jo sokaig egy elerhetetlen Socket-ed nyitva. Es ha a foo() ujra meghivodik, akkor majd a bind() elhasal es megvan a baj.
Gondolom van erre okos felmegoldas a java-ban, pl. a Socket osztaly finalizere megnezi, hogy nyitva van-e a socket es ha igen, akkor bezarja. Akkor mondjuk a kovetkezo gc-ig all csak a problema, de ez mindenesetre nem korrekt eroforraskezeles (megserti az 1. kriteriumot).
Es arra hogy rosszul hasznalod az objektumot, arra nincs warning, nincs semmi (sajnos ezt eleg nehez lenne kikovetkeztetni a forditonak).
Nekem eros a gyanum, hogy a Java programok egy jo reszeben ezzel a gc-be patkolt close()-al tortenik az implicit eroforras management. Bar tobbnyire ez valid mukodest eredmenyez, de nagyon nem hatekony...