2013-08-20 10 views
7

Doświadczony programista nowy w Java poszukuje mądrości:techniki Java dla end-of-życia obiektów

Jeśli nie ma sposobu, aby upewnić się, że niektóre szczególności kod kawałek jest wykonywany jako przedmiot wykracza poza zakres, a następnie co czy istnieją inne podejścia, które oferowałyby taką samą funkcjonalność? (wydaje się sfinalizować wyraźnie nie oznaczało dla tego)

Klasycznym przykładem jest lunetą blokada idiom:

void method() 
{ 
    // Thread-unsafe operations {...} 

    { // <- New scope 
     // Give a mutex to the lock 
     ScopedLock lock(m_mutex); 

     // thread safe operations {...} 

     if (...) return; // Mutex is unlocked automatically on return 

     // thread safe operations {...} 

    } // <- End of scope, Mutex is unlocked automatically 

    // Thread-unsafe operations {...} 
} 

Mogę zrozumieć, że w Javie byłoby mile widziana mieć jakiś kod wykonywany jeśli ciebie nie nazwałem tego wyraźnie. Uważam jednak, że możliwość egzekwowania niektórych kodów, które mają zostać wykonane po zakończeniu okresu istnienia obiektu, jest bardzo ważną funkcją zapewniającą rozsądne korzystanie z klas przez kod klienta. Dzięki

+0

Zgadzam się, jest potężny. Szkoda, że ​​Java nie miała czasami czegoś takiego jak C# 'use'. +1 Edytuj: Zgadnij, że Java ma to. zobacz odpowiedź OldCurmudgeon. Jeśli nie korzystasz z Java 7, skorzystam z podejścia try/finally na temat błędów. Chociaż do blokowania nie ma automatycznego sterowania. –

Odpowiedz

1

Jeśli chcesz jakiś kod do uruchomienia w każdym razie w sposobie, wystarczy użyć try ... finally .... Blok finally jest gwarantowana do uruchomienia. Lub, w Javie 7, używa bloku "z".

Jeśli chcesz, aby jakiś kod działał jak destruktor C++. Obawiam się, że nie ma czegoś takiego w Javie. Metoda finalizacji nie jest niezawodna i nie można jej użyć do obsługi misji krytycznych. Normalnie sposób działania klas Java polega na udostępnieniu metody czyszczenia (na przykład close() tych klas strumieni), aby klient wywoływał tę metodę jawnie w celu wykonywania zadań czyszczenia.

+0

Jedną z rzeczy, które widzę sporadycznie, jest użycie metody "finalize", aby krzyczeć na ciebie w dziennikach, jeśli obiekt nie został oczyszczony. Nie można polegać na faktycznym oczyszczeniu, ale możesz go użyć do znalezienia błędów tam, gdzie nie posprzątałeś. –

2

Od wersji 7 Java jest automatyczne zarządzanie zasobami. Jeśli twój zamek jest pod twoją kontrolą, zmusisz go do wdrożenia AutoCloseable. Niestety, zamki java.util.concurrent nie implementują tego interfejsu. Here's a good reference do szczegółów tego.

9

Ogólnie - jeśli istnieje potrzeba zamknięcia/usunięcia zasobów, zaleca się stosowanie struktury try{} finally{}.

// The old way - using try/finally 
    Statement stmt = con.createStatement(); 
    try { 
    ResultSet rs = stmt.executeQuery(query); 
    while (rs.next()) { 
     // ... 
    } 
    } catch (SQLException e) { 
    // Whatever ... . 
    } finally { 
    // Be sure to close the statement. 
    if (stmt != null) { 
     stmt.close(); 
    } 
    } 

Nowsze inkarnacje java mieć interfejs AutoCloseable które można wykorzystać z mechanizmem with. Wszystkie obiekty Closeable są automatycznie AutoCloseable.

// Example of what is called try-with 
    try (Statement stmt = con.createStatement()) { 
    ResultSet rs = stmt.executeQuery(query); 
    while (rs.next()) { 
     // ... 
    } 
    } catch (SQLException e) { 
    // Whatever ... stmt will be closed. 
    } 
+0

+1, nie wiedziałem, że to istnieje. Więc myślę, że Java ma teraz odpowiednik instrukcji 'using' języka C#. –

+0

Forma try (resource) wydaje się być najbardziej zbliżoną do rzeczywistości. Wymaga to jednak od klienta odpowiedniego kodu. Ale co, jeśli wewnętrzny zasób wewnątrz obiektu Statement jest szczegółem implementacji, o którym użytkownik nie powinien wiedzieć? Czy istnieje sposób, aby uzyskać close() do wykonania bez wyraźnych środków wymaganych przez użytkownika? – user1659313

+1

Nie, nie ma. Nawet próba z zasobami była dyskutowana o tej nieoczywistościowej charakterystyce, co jest sprzeczne z duchem Javy, a zatem przeciwko intuicyjnej intuicji programisty Java. –

1

Inną opcją zastąpienia finalize metody jest PhantomReference. Jeśli chcesz wykonać jakąś czynność, zanim obiekt zostanie zbuforowany, wówczas oferuje inne dobre podejście lepsze niż metoda finalize.

Sprawdź na przykład tutaj: https://weblogs.java.net/blog/kcpeppe/archive/2011/09/29/mysterious-phantom-reference

+0

Nie ma gwarancji, że obiekt zostanie zebrany śmieci. – jontro

+0

Zacytuj OP: "Wygląda na to, że sfinalizowanie nie jest do tego przeznaczone". I on ma rację. –

+0

Rozumiem, że z sfinalizowaniem metody nie można jej zagwarantować, ale z fantomową referencją może ona również nie zostać zebrana? – Lokesh

Powiązane problemy