Jaki jest sens "klasy końcowej" w Javie?

Czytam książkę o Javie i jest w niej napisane, że możesz zadeklarować całą klasę jako final. Nie mogę wymyślić niczego, gdzie bym tego użył.

Jestem po prostu nowy w programowaniu i zastanawiam sięczy Programiści faktycznie używają tego w swoich programach . Jeśli tak, to kiedy go używają, żebym mógł go lepiej zrozumieć i wiedzieć, kiedy go używać.

Jeśli Java jest zorientowana obiektowo, a deklarujesz klasę final, czy to nie zatrzymuje idei klasy o cechach przedmioty?

 432

23 answers

Jeśli tak, to kiedy go używają, żebym mógł go lepiej zrozumieć i wiedzieć, kiedy go używać.

A final klasa jest po prostu klasą, której nie można rozszerzyć.

(nie oznacza to, że wszystkie odwołania do obiektów klasy zachowywałyby się tak, jakby zostały zadeklarowane jako final.)

Kiedy warto zadeklarować klasę jako ostateczną, jest to opisane w odpowiedziach na to pytanie:

Jeśli Java jest zorientowana obiektowo i deklarujesz klasę final, czy to nie powstrzymuje idei klasy o cechach obiektów?

W pewnym sensie tak.

Oznaczając klasę jako ostateczną, wyłączasz potężną i elastyczną funkcję języka dla tej części kodu. Jednak niektóre klasy nie powinny (a w niektórych przypadkach mogą nie) być zaprojektowane tak, aby w dobry sposób uwzględniać podklasę. W takich przypadkach ma sens oznaczyć klasę jako ostateczną, mimo że ogranicza OOP. (Pamiętajmy jednak, że Klasa końcowa może jeszcze rozszerzyć klasę nie końcową.)


Pokrewny artykuł: Java: kiedy utworzyć klasę końcową

 410
Author: aioobe,
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
2017-05-23 12:03:07

W Javie elementy z modyfikatorem final nie mogą być zmieniane!

Obejmuje to Klasy końcowe, zmienne końcowe i metody końcowe:

  • Klasa końcowa nie może być rozszerzona o żadną inną klasę
  • zmiennej końcowej nie można przypisać innej wartości
  • ostateczna metoda nie może być nadpisana
 158
Author: andyqee,
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
2018-06-17 16:26:18

Jeden scenariusz, w którym finał jest ważny, gdy chcesz zapobiec dziedziczeniu klasy, ze względów bezpieczeństwa. Pozwala to upewnić się, że kod, który używasz , nie może zostać nadpisany przez kogoś.

Inny scenariusz dotyczy optymalizacji: zdaje się, że pamiętam, że kompilator Javy wywołuje niektóre funkcje z końcowych klas. Tak więc, jeśli wywołasz a.x() I A jest zadeklarowane final, wiemy w czasie kompilacji jaki będzie kod i możemy wprowadzić go do funkcji wywołującej. Nie mam pojęcia, czy jest to rzeczywiście zrobione, ale z ostatecznym jest to możliwe.

 27
Author: Shay Rojansky,
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-05-14 18:51:30

Najlepszym przykładem jest

Public final class String

Która jest klasą niezmienną i nie może być rozszerzona. Oczywiście, jest coś więcej niż tylko uczynienie klasy ostatecznym niezmiennym.

 18
Author: javadeveloper,
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-03-06 00:49:20

Jeśli wyobrażasz sobie hierarchię klas jako drzewo (jak to jest w Javie), klasy abstrakcyjne mogą być tylko gałęziami, a klasy końcowe to te, które mogą być tylko liśćmi. Klasy, które nie należą do żadnej z tych kategorii, mogą być zarówno gałęziami, jak i liśćmi.

Nie ma tu łamania zasad OO, final jest po prostu miłą symetrią.

W praktyce chcesz użyć final, jeśli chcesz, aby twoje obiekty były niezmienne lub jeśli piszesz API, aby zasygnalizować użytkownikom API, że klasa nie jest przeznaczona do rozszerzenia.

 15
Author: biziclop,
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
2011-03-03 13:59:50

Odpowiednie czytanie: Zasada otwarta-zamknięta autorstwa Boba Martina.

Cytat:

Encje Oprogramowania (Klasy, Moduły, Funkcje itp.) powinny być otwarte dla Przedłużenie, ale zamknięte dla Modyfikacja.

Słowo kluczowe final służy do wymuszania tego w Javie, niezależnie od tego, czy jest używane w metodach, czy w klasach.

 15
Author: Sean Patrick Floyd,
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
2018-01-08 19:59:11

Samo słowo kluczowe final oznacza, że coś jest ostateczne i nie powinno być w żaden sposób modyfikowane. If a class if marked final then it cannot be extended or sub-classified. Ale pytanie brzmi dlaczego oznaczamy klasę final? IMO są różne powody:

  1. standaryzacja: Niektóre klasy wykonują funkcje standardowe i nie mają być modyfikowane np. klasy wykonujące różne funkcje związane z manipulacjami łańcuchami lub funkcjami matematycznymi itd.
  2. względy bezpieczeństwa : czasami piszemy klasy, które wykonują różne funkcje związane z uwierzytelnianiem i hasłem i nie chcemy, aby były zmieniane przez kogokolwiek innego.

Słyszałem, że Klasa znakowania final poprawia efektywność, ale szczerze mówiąc, nie mogłem znaleźć tego argumentu, który nosiłby dużą wagę.

Jeśli Java jest zorientowana obiektowo i deklarujesz klasę ostateczną, prawda zatrzymać ideę klasy o cechach przedmioty?

Być może tak, ale czasami jest to zamierzony cel. Czasami robimy to, aby osiągnąć większe korzyści z bezpieczeństwa itp. poświęcając zdolność tej klasy do rozszerzenia. Ale ostatnia klasa może jeszcze przedłużyć jedną klasę, jeśli będzie taka potrzeba.

Na marginesie powinniśmy preferować kompozycję niż dziedziczenie i final słowo kluczowe rzeczywiście pomaga w egzekwowaniu tej zasady.

 9
Author: i_am_zero,
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
2017-05-23 11:54:50

Jeśli klasa jest oznaczona final, oznacza to, że struktura klasy nie może być modyfikowana przez nic zewnętrznego. Tam, gdzie jest to najbardziej widoczne, jest to, gdy robisz tradycyjne dziedziczenie polimorficzne, w zasadzie class B extends A po prostu nie zadziała. Jest to w zasadzie sposób na ochronę niektórych części kodu (w stopniu) .

Dla wyjaśnienia, oznaczanie klasy final nie oznacza jej pól jako final i jako takie nie chroni właściwości obiektu, ale rzeczywistą strukturę klasy.

 5
Author: Esko,
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
2011-03-03 13:57:46

Bądź ostrożny, gdy uczynisz klasę "ostateczną". Ponieważ jeśli chcesz napisać test jednostkowy dla ostatecznej klasy, nie możesz podklasować tej ostatecznej klasy, aby użyć techniki łamania zależności "Subclass and Override Method" opisanej w książce Michaela C. Feathersa "Working Effectively with Legacy Code". W książce tej Feathers powiedział: "poważnie, łatwo jest uwierzyć, że sealed i final są błędem, że nigdy nie powinny być dodawane do języków programowania. Ale prawdziwe wina leży po naszej stronie. Kiedy polegamy bezpośrednio na bibliotekach, które są poza naszą kontrolą, po prostu prosimy o kłopoty."

 5
Author: Ben Wu,
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-06-10 00:15:58

ABY ROZWIĄZAĆ KOŃCOWY PROBLEM KLASOWY:

Są dwa sposoby na zakończenie zajęć. Pierwszym jest użycie słowa kluczowego final w deklaracji klasy:
public final class SomeClass {
  //  . . . Class contents
}

Drugim sposobem na zakończenie klasy jest zadeklarowanie wszystkich jej konstruktorów jako prywatnych:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

Oznaczanie go jako końcowy oszczędza ci kłopotu, jeśli dowiesz się, że jest to ostateczny, aby zademonstrować spojrzenie na tę klasę testową. wygląda publicznie na pierwszy rzut oka.

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

Niestety, ponieważ tylko konstruktor klasy jest prywatny, nie można rozszerzyć tej klasy. W przypadku klasy testowej nie ma powodu, aby klasa była ostateczna. Klasa testowa jest dobrym przykładem tego, jak Ukryte klasy końcowe mogą powodować problemy.

Więc powinieneś oznaczyć ją jako ostateczną, gdy w domyśle uczynisz klasę ostateczną, czyniąc jej konstruktor prywatnym.

 5
Author: mel3kings,
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-06-21 06:34:23

final class można uniknąć łamania publicznego API po dodaniu nowych metod

Załóżmy, że w wersji 1 twojej klasy Base wykonujesz:

public class Base {}

A klient robi:

class Derived extends Base {
    public int method() { return 1; }
}

Wtedy jeśli w wersji 2 chcesz dodać metodę method do Base:

class Base {
    public String method() { return null; }
}
To złamałoby kod klienta.

Gdybyśmy zamiast tego użyli final class Base, klient nie byłby w stanie dziedziczyć, a dodanie metody nie złamałoby API.

 4
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
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
2018-05-22 08:07:28

Tak, Czasami możesz tego chcieć, ze względów bezpieczeństwa lub prędkości. Robi się to również w C++. Może nie to dotyczy programów, ale raczej frameworków. http://www.glenmccl.com/perfj_025.htm

 3
Author: James,
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
2011-03-03 13:56:39

Klasa końcowa to klasa, której nie można rozszerzyć. Również metody mogą być zadeklarowane jako ostateczne, aby wskazać, że nie mogą być nadpisywane przez podklasy.

Zapobieganie podklasowaniu klasy może być szczególnie przydatne, jeśli piszesz API lub biblioteki i chcesz uniknąć rozszerzenia w celu zmiany podstawowego zachowania.

 3
Author: JuanZe,
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
2011-03-03 14:01:21

Jedna zaleta utrzymania klasy jako ostatecznej: -

Klasa String jest zachowywana jako ostateczna, więc nikt nie może nadpisać jej metod i zmienić funkcjonalności. np. nikt nie może zmienić funkcjonalności metody length (). Zawsze zwróci Długość łańcucha.

Twórca tej klasy chciał, aby nikt nie zmieniał jej funkcjonalności, więc zachował ją jako ostateczną.

 3
Author: Rahul,
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-01-04 09:47:14

Klasy końcowe nie mogą być przedłużane. Więc jeśli chcesz, aby Klasa zachowywała się w określony sposób i nie nadpisywała metod (z prawdopodobnie mniej wydajnym i bardziej złośliwym kodem), możesz zadeklarować całą klasę jako ostateczne lub konkretne metody, których nie chcesz zmieniać.

Ponieważ deklarowanie klasy nie uniemożliwia tworzenia instancji klasy, nie oznacza to, że powstrzyma klasę przed posiadaniem właściwości obiektu. Po prostu będziesz musiał trzymać się metody tak, jak są deklarowane w klasie.

 1
Author: skhaapioloir,
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
2012-10-26 00:32:47

Pomyśl o finale jako o "końcu linii" - ten facet nie może już produkować potomstwa. Więc kiedy widzisz to w ten sposób, Istnieje mnóstwo rzeczywistych scenariuszy, które można natknąć się, które wymaga, aby oznaczyć "koniec linii" znacznik do klasy. Jest to Domain Driven Design - jeśli Twoja domena wymaga, aby dana jednostka (klasa) nie mogła utworzyć podklas, oznacz ją jako ostateczną.

Należy zauważyć, że nic nie stoi na przeszkodzie dziedziczeniu klasy "powinny być oznaczone jako końcowe". Ale jest to zazwyczaj klasyfikowane jako "nadużycie dziedziczenia" i robione, ponieważ najczęściej chcesz dziedziczyć jakąś funkcję z klasy bazowej w swojej klasie.

Najlepszym podejściem jest spojrzeć na domenę i pozwolić jej dyktować decyzje projektowe.

 1
Author: Kingz,
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-09-25 20:53:39

Jak wspomniano powyżej, jeśli chcesz, aby nikt nie mógł zmienić funkcjonalności metody, możesz zadeklarować ją jako ostateczną.

Przykład: ścieżka do pliku serwera aplikacji do pobrania/uploadu, podział łańcucha na offset, takie metody można zadeklarować jako ostateczne, aby te funkcje metody nie były zmieniane. I jeśli chcesz, aby takie ostateczne metody były w osobnej klasie, zdefiniuj tę klasę jako klasę końcową. Tak więc Klasa końcowa będzie miała wszystkie metody końcowe, gdzie jako metodę ostateczną Można zadeklarować i zdefiniowana w klasie niekończącej.

 1
Author: lok,
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-11-26 17:17:01

Android Looper class jest tego dobrym praktycznym przykładem. http://developer.android.com/reference/android/os/Looper.html

Klasa Looper zapewnia pewną funkcjonalność, która nie jest przeznaczona do nadpisywania przez żadną inną klasę. Stąd nie ma tu żadnej podklasy.

 1
Author: jaamit,
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-03-27 08:44:14

Klasa Final jest używana, gdy chcesz ustandaryzować metody i upewnić się, że nie są one nadpisane przez kogoś innego.
Dlaczego więc niektóre klasy są zadeklarowane jako ostateczne?

  1. ponieważ Klasy końcowe nie mogą być rozszerzone, możesz traktować je jak prymitywy i nie musisz się martwić, że te klasy zostaną zmienione.
  2. ze względów bezpieczeństwa, nie chcesz, aby kod napisany przez Ciebie został nadpisany przez kogoś innego.
 1
Author: Pooja Khatri,
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
2018-05-31 03:51:44

Jeśli uczynisz jakąś klasę jako ostateczną, nie możesz jej przedłużyć.

final class Bike{}  

class Honda1 extends Bike{  
 void run(){System.out.println("running safely with 100kmph");}  

public static void main(String args[]){  
 Honda1 honda= new Honda();  
honda.run();  
  }  
}  

    Output:Compile Time Error
 0
Author: Ved Prakash,
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
2017-01-03 04:53:47

Wkrótce Klasa, zmienna lub metoda zadeklarowana jako ostateczna nie może zostać zmieniona.

Ważniejsze jest moje zdanie:

Szczerze, uważam, że słowo kluczowe {[0] } jest błędem, ponieważ jego istnienie pozwala użytkownikowi zdefiniować coś, co jest nie final. Wszystko w Javie powinno być domyślnie final z wyjątkiem metod interfejsu (według jego definicji). Niefortunnym wyborem było, aby wszystkie metody instancji były domyślnie virtual (w kategoriach c # ). Kluczem jest wymusić na użytkowniku myślenie pierwsze i wyraźnie zdefiniować haniebnie metodę jako virtual zamiast tego-to sprawi, że zadałby sobie pytanie, czy ta metoda powinna pozwolić innym ją nadpisać, czy jest to potrzeba really, czy też nakłonić go do przeprojektowania kodu.

 0
Author: Nikolas,
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
2018-06-08 21:52:07

Powiedzmy, że masz Employee klasę, która ma metodę greet. Po wywołaniu metody greet po prostu wyświetla Hello everyone!. Więc to jest oczekiwane zachowanie Z metody greet

public class Employee {

    void greet() {
        System.out.println("Hello everyone!");
    }
}

Teraz pozwól GrumpyEmployee podklasę Employee i nadpisać greet metodę, jak pokazano poniżej.

public class GrumpyEmployee extends Employee {

    @Override
    void greet() {
        System.out.println("Get lost!");
    }
}

Teraz w poniższym kodzie spójrz na metodę sayHello. Pobiera instancję Employee jako parametr i wywołuje metodę greet mając nadzieję, żeHello everyone! ale dostajemy to Get lost!. Ta zmiana w zachowaniu jest spowodowana Employee grumpyEmployee = new GrumpyEmployee();

public class TestFinal {
    static Employee grumpyEmployee = new GrumpyEmployee();

    public static void main(String[] args) {
        TestFinal testFinal = new TestFinal();
        testFinal.sayHello(grumpyEmployee);
    }

    private void sayHello(Employee employee) {
        employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
    }
}

Taka sytuacja może być unika się Jeśli Employee klasa została wykonana final. Wyobraź sobie, jaki chaos mógłby spowodować bezczelny programista, gdyby Klasa String nie została zadeklarowana jako final.

 0
Author: Andy,
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
2018-07-06 21:31:30

Orientacja obiektu nie polega na dziedziczeniu, lecz na enkapsulacji. I dziedziczenie łamie enkapsulację.

Ogłaszanie matury klasowej ma sens w wielu przypadkach. Każdy obiekt reprezentujący "wartość", taki jak kolor lub kwota pieniędzy, może być ostateczny. Stoją same.

Jeśli piszesz biblioteki, uczyń swoje klasy ostatecznymi, chyba że wyraźnie wcięjesz je do wyprowadzenia. W przeciwnym razie ludzie mogą czerpać z Twoich klas i nadpisywać metody, łamiąc Twoje założenia / niezmienniki. Może to również mieć wpływ na bezpieczeństwo.

Joshua Bloch w" Effective Java " zaleca projektowanie jawnie dla dziedziczenia lub zakazuje go i zauważa, że projektowanie dla dziedziczenia nie jest takie proste.

 -2
Author: Wilhem Meignan,
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
2014-08-06 15:04:12