Java final modifier

Powiedziano mi, że nie rozumiem skutków final. Jakie są efekty słowa kluczowego final?

Oto krótki przegląd tego, co myślę, wiem:

Java final modifier (aka agregation relation)

Prymitywne zmienne : można ustawić tylko raz. (pamięć i wydajność zysk)
zmienne objects : mogą być modyfikowane, final dotyczy obiektu Referencja.
pola: można ustawić tylko raz.
metody : nie może być przesłonięta, ukryta.
klasy: nie można rozszerzyć.
garbage collection : wymusi pokoleniowe zbieranie śmieci w Javie mark-sweep do double sweep.

Can 's and Cant' s

    Może sprawić, że klon zawiedzie (jest to zarówno dobre, jak i złe)]}
  • może tworzyć niezmienne prymitywy aka const
  • W ten sposób można stworzyć puste pole, które jest niezmienne - inicjowane przy tworzeniu aka readonly.]}
  • może sprawić, że obiekty będą płytko niezmienne
  • można zrobić zakres / visibility immutable
  • Może sprawić, że narzut wywołania metody będzie mniejszy (ponieważ nie wymaga wirtualnej tabeli).]}
  • może sprawić, że argumenty metody będą ostateczne (nawet jeśli nie są)
  • może tworzyć obiekty threadsafe (jeśli obiekt jest zdefiniowany jako końcowy, to argumenty metody nie będą ostateczne)
  • może robić fałszywe testy (nie żebyś mógł coś z tym zrobić - możesz powiedzieć, że błędy są przeznaczone)
  • Can ' t make friends (mutable with other friends and immutable for reszta)
  • nie można zmienić zmiennego, który jest zmieniany na niezmienny później (ale może z fabrycznym wzorem jak fix)
  • nie można uczynić elementów tablicy niezmiennymi aka głęboko niezmiennymi
  • Nie można tworzyć nowych instancji obiektu (jest to zarówno dobre, jak i złe)]}
  • nie można uruchomić serializacji

Nie ma alternatyw dla final, ale jest wrapper + private I enums.

 49
Author: Margus, 2010-10-25

2 answers

Odpowiadając na każde z twoich punktów po kolei:

Prymitywne zmienne: można ustawić tylko raz. (wzmocnienie pamięci i wydajności)

Tak, ale bez wzmocnienia pamięci i wydajności. (Domniemany przyrost wydajności pochodzi z Ustawienia tylko raz ... nie z final.)

Zmienne obiektów: mogą być modyfikowane, final odnosi się do odniesienia do obiektu.

Tak. (Jednak Opis Ten pomija punkt, że jest to całkowicie zgodne z sposób, w jaki reszta języka Java radzi sobie z dualnością obiekt / odniesienie. Na przykład, gdy obiekty są przekazywane jako parametry i zwracane jako wyniki.)

Pola: można ustawić tylko raz.

Prawdziwa odpowiedź brzmi: taka sama jak dla zmiennych.

Metody: nie można przesłonić, ukryć.

Tak. Ale zauważ również, że to, co się tutaj dzieje, to to, że słowo kluczowe final jest używane w innym kontekście składniowym, aby coś znaczyć inny niż final dla pola / Zmiennej.

Klasy: nie można rozszerzać.

Tak. Ale również patrz uwaga powyżej.

Garbage collection: wymusi użycie znacznika-zamiatania pokoleniowego w Javie do podwójnego zamiatania.

To nonsens. Słowo kluczowe {[0] } nie ma znaczenia W ogóle dla garbage collection. Możesz pomylić final z finalizacją ... nie są ze sobą powiązane.

Ale nawet finalizatorzy nie Wymuś dodatkowe przeszukanie. Dzieje się tak, że obiekt, który wymaga finalizacji, jest ustawiany z jednej strony, dopóki główny GC się nie skończy. Następnie GC uruchamia metodę finalize na obiekcie i ustawia jego flagę ... i trwa. Przy następnym uruchomieniu GC obiekt jest traktowany jako normalny obiekt:

  • jeśli jest osiągalny, jest oznaczany i kopiowany
  • jeśli nie jest osiągalny, nie jest oznaczony.

(twoja charakterystyka - "Java generative garbage collection mark-sweep" jest zniekształcony. Garbage collector może być "mark-sweep" lub " generative "(podklasa"kopiowanie"). To nie może być jedno i drugie. Java zwykle używa kolekcji pokoleniowej i wraca do funkcji mark-sweep tylko w sytuacjach awaryjnych, np. gdy zabraknie miejsca lub gdy kolekcjoner małej pauzy nie może nadążyć.)

Może sprawić, że klon zawiedzie (jest to zarówno dobre, jak i złe)

Nie sądzę.

Potrafi tworzyć niezmienne prymitywy const

Tak.

Może sprawić, że puste immutable-zainicjalizowane przy tworzeniu aka readonly

Tak ... chociaż nigdy wcześniej nie słyszałem określenia "pusty niezmienny".

Może sprawić, że obiekty będą płytko niezmienne

Zmienność obiektu polega na tym, czy obserwowalny stan może ulec zmianie. Jako takie deklarowanie atrybutów final może sprawić, że obiekt zachowa się jako niezmienny. Poza tym pojęcie "płytko niezmienne" nie jest dobrze definiowane, nie tylko dlatego, że pojęcia tego, co jest" płytkie", nie można odwzorować bez głębokiej znajomości semantyki klasy.

(aby było jasne, zmienność zmiennych / pól jest dobrze zdefiniowanym pojęciem w kontekście JLS. To właśnie koncepcja zmienności obiektów jest niezdefiniowana z perspektywy JLS.)

Może sprawić, że zakres / widoczność będą niezmienne

Błąd terminologiczny. Zmienność dotyczy stanu obiektu. Widoczność i zakres nie są.

Może zmniejszyć obciążenie wywołania metody (ponieważ nie potrzebuje wirtualnej tabeli)

W praktyce jest to nieistotne. Nowoczesny kompilator JIT wykonuje tę optymalizację również dla metod niekończących się, jeśli nie są one nadpisywane przez żadną klasę, której aplikacja faktycznie używa. (Sprytne rzeczy się zdarzają ...)

Może sprawić, że argumenty metody będą ostateczne (nawet jeśli nie są)

Huh? Nie mogę tego przeanalizować. zdanie.

Może tworzyć threadsafe obiektów

W pewnych sytuacjach tak.

(jeśli obiekt jest zdefiniowany jako końcowy, to argumenty metody nie będą ostateczne)

Tak, jeśli masz na myśli, jeśli Klasa jest ostateczna. Obiekty nie są ostateczne.

Może robić symulacje (nie żebyś mógł nic z tym zrobić - możesz powiedzieć, że błędy są zamierzone)

Nie analizuje.

Can ' t make friends (mutable with inni przyjaciele i niezmienni na odpoczynek)

Java nie ma "przyjaciół".

Nie można zmienić mutable, który jest zmieniany na niezmienny później (ale może z fabrycznym wzorem jak fix)

Tak dla pierwszego, pola final nie można przełączyć z zmiennego na niezmienny.

Nie jest jasne, co masz na myśli przez drugą część. Prawdą jest, że można użyć wzorca fabrycznego (lub konstruktora) do konstruowania obiektów niezmiennych. Jeśli jednak użyjesz final do pola obiektu w żadnym punkcie nie będą podlegały zmianie.

Alternatywnie można zaimplementować obiekty niezmienne, które używają niekończących się pól do reprezentowania stanu niezmiennego, a także można zaprojektować API tak, aby można było "przerzucić przełącznik", aby wcześniej zmieniany obiekt stał się niezmienny od teraz. Ale jeśli podejmiesz takie podejście, musisz być o wiele bardziej ostrożny z synchronizacją ... jeśli twoje obiekty muszą być bezpieczne dla wątku.

Nie można sprawić, by elementy tablicy były niezmienne immutable

Tak, ale twoja terminologia jest zepsuta; patrz komentarz powyżej o "płytkiej zmienności".

Nie można tworzyć nowych instancji obiektu (jest to zarówno dobre, jak i złe)

Nie. Nic nie stoi na przeszkodzie, aby utworzyć nową instancję obiektu z końcowymi polami, końcową klasą lub końcowymi metodami.

Nie można uruchomić serializacji

Nie. Serializacja działa. (Przyznane, deserializacja final pól za pomocą niestandardowego readObject metoda przedstawia problemy ... chociaż możesz obejść je za pomocą hacków odbicia.)

Nie ma alternatyw dla finalnego,

Zgadza się.

Ale jest wrapper + private

Tak, modulo, że (ściśle mówiąc) niezsynchronizowany getter dla niekończącego się pola może nie być bezpieczny dla wątku ... nawet jeśli jest inicjowany podczas budowy obiektu i nigdy nie zmieniany!

I enums.

Rozwiązuje inny problem. I enums mogą być mutowalne.

 71
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-02 00:37:04

Ostatnie słowo kluczowe jest zwykle używane do zachowania niezmienności. Aby użyć final dla klas lub metod, należy zapobiec zerwaniu powiązań między metodami. Na przykład, załóżmy, że implementacja jakiejś metody klasy X zakłada, że metoda M będzie zachowywać się w określony sposób. Deklarowanie X lub M jako ostatecznego uniemożliwi klasom pochodnym przedefiniowanie M w taki sposób, aby x zachowywał się nieprawidłowo.

 2
Author: Khushi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-28 19:30:32