Witam. Piszę prosty program o następującej treści:
Utwórz klasę o nazwie Tank() obsłuhgującą operację fill() i empty() wyposażoną w warunek zakończenia wymagający opróżnienia obiektu przed usunieciem. Napisz metode finalize() ktora bedzie sprawdzac stan zbiornika. W metodzie main() sprawdz mozliwe scenariusze używania obiektów klasy Tank.
Napisałem coś takiego:
class Tank {
boolean pelny = false;
void fill() {
pelny = true;
}
void empty() {
pelny = false;
}
protected void finalize() {
if(pelny) {
System.out.println("Blad");
} else {
System.out.println("Obiekt usuniety");
}
}
}
public class Glowna {
public static void main(String[] args) {
}
}
I przykładowo robię coś takiego:
public class Glowna {
public static void main(String[] args) {
Tank t = new Tank();
t.fill();
t.empty();
System.gc();;
}
}
W konsoli nie otrzymuję niczego. Czyli jak to jest z tym odśmiecaczem, który wywołuję System.gc? Czy nie powinna zostać uruchomiona wtedy ta metoda finalize i wypisać mi na ekranie "Obiekt usuniety"? Wiem, że przy wywołaniu System.gc obiekty mogą zostać usunięte, ale nie muszą. W takim razie po co jest w ogóle ta metoda finalize i to sprawdzanie warunków czy zbiornik będzie pełny czy pusty? Przecież ona nie daje informacji GC czy obiekt ma zostać usunięty jeśli zbiornik = false czy go pozostawić jeśli = true.
Teraz 2 przypadek:
public class Glowna {
public static void main(String[] args) {
Tank t = new Tank();
t.fill();
t.empty();
t.finalize();
}
}
W odpowiedzi otrzymuję oczywiście "Obiekt został usunięty" i ok. Ale jeśli zrobię np. tak:
public class Glowna {
public static void main(String[] args) {
Tank t = new Tank();
t.fill();
t.empty();
t.finalize();
t.fill();
t.empty();
}
}
Czyli po finalize() odwołam się znów do obiektu t to nie wyskakuje żaden błąd. Tak jakby ten obiekt nadal istniał, a nie został usunięty przez finalize?
I ostatni przypadek
public class Glowna {
public static void main(String[] args) {
Tank t = new Tank();
t.fill();
t.empty();
new Tank().fill();
t.finalize();
System.gc();
}
}
Gdy usunę t.finalize() to nic nie wyskakuje. A przecież System.gc() wymusza to odśmiecanie i new Tank().fill(); nie ma referencji, więc powinien na wyjściu pojawić się komunikat "Błąd" co jednak się nie dzieje. W momencie kiedy dodam t.finalize() to pojawia się już komunikat o błędzie. Czemu to się dzieje w tym przypadku a w poprzednim nie? Przecież t.finalize() wywołuję na rzecz obiektu t a nie żadnych innych.
Ogólnie nie do końca rozumiem bardzo znaczenia tej metody finalize. Wiem, że jest dość rzadko używana, ale jednak chciałbym jakoś ją zrozumieć. Z tego co wnioskuję to tak jakby miała on charakter bardziej informacyjny? Kiedy obiekt jest usuwany przez GC, wtedy wywoływana jest metoda finalize? A przykładowo wywołanie samemu tej metody na rzecz jakiegoś obiektu typu t.finalize() wcale nie musi usunąć obiektu? Służy ona głównie do czyszczenia miejsca w pamięci kiedy pamięć jest alokowana w sposób niestandardowy? Wtedy np. tworzymy takową metodę finalize i w niej np. robimy wszystkie czynności potrzebne do odśmiecania np.
protected void finalize() {
free(coś tam);
}
I dopiero w takim przypadku wywołanie typu jakiśobiekt.finalize() ma jakiś sens? I wtedy rzeczywiście pamięć zostanie wyczyszczona?