Dlaczego zmienne statyczne są uważane za złe?

Jestem programistą Java, który jest nowy w świecie korporacji. Ostatnio opracowałem aplikację wykorzystującą Groovy i Javę. Przez cały kod, który napisałem, używałem całkiem sporej liczby statyk. Zostałem poproszony przez starszy zespół techniczny, aby zmniejszyć liczbę używanych statyk. Wygooglowałem o tym samym i uważam, że wielu programistów jest przeciwko używaniu zmiennych statycznych.

Uważam, że statyczne zmienne są wygodniejsze w użyciu. I zakładam, że oni też są skuteczni (Proszę mnie poprawić, jeśli się mylę), ponieważ gdybym musiał wykonać 10 000 wywołań do funkcji w klasie, byłbym zadowolony, aby metoda stała i użyć prostego Class.methodCall() na nim zamiast zaśmiecać pamięć 10 000 instancji klasy, prawda?

Ponadto statyka zmniejsza wzajemne zależności od innych części kodu. Mogą działać jako doskonali posiadacze Państwa. Dodając do tego stwierdzam, że statyki są szeroko zaimplementowane w niektórych językach, takich jak Smalltalk i Scala . Dlaczego więc ten ucisk dla statyki jest powszechny wśród programistów (szczególnie w świecie Javy)?

PS: proszę popraw mnie, jeśli moje założenia dotyczące statyki są błędne.

 536
Author: Md. Abu Nafee Ibna Zahid, 2011-08-11

28 answers

Zmienne statyczne reprezentują stan globalny. Trudno o to wnioskować i trudno testować: jeśli utworzę nową instancję obiektu, mogę wnioskować o jego nowym stanie w testach. Jeśli używam kodu, który używa zmiennych statycznych, może on być w dowolnym stanie - i wszystko może go modyfikować.

Mógłbym kontynuować przez jakiś czas, ale większa koncepcja do myślenia jest taka, że im węższy zakres czegoś, tym łatwiej jest rozumować. Jesteśmy dobrzy w myśleniu o małych rzeczach, ale trudno zrozumieć stan systemu liniowego miliona, jeśli nie ma modułowości. Tak nawiasem mówiąc, dotyczy to wszelkiego rodzaju rzeczy - nie tylko zmiennych statycznych.

 607
Author: Jon Skeet,
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-08-11 13:18:22

Jej niezbyt obiektowo zorientowany: Jednym z powodów, dla których statyka może być uważana przez niektórych za " złą " jest to, że jest ona sprzeczna z paradygmatem zorientowanym obiektowo. W szczególności narusza to zasadę, że dane są hermetyzowane w obiektach (które mogą być rozszerzane, ukrywane informacje itp.). Statyka, w sposób, w jaki je opisujesz, polega zasadniczo na używaniu ich jako zmiennej globalnej, aby uniknąć radzenia sobie z problemami takimi jak zakres. Jednak zmienne globalne są jednym z definiujących cechy paradygmatu programowania proceduralnego lub imperatywnego, a nie cecha "dobrego" kodu obiektowego. Nie oznacza to, że paradygmat proceduralny jest zły, ale odnoszę wrażenie, że twój przełożony oczekuje od Ciebie pisania "dobrego kodu zorientowanego obiektowo" i naprawdę chcesz napisać "dobry kod proceduralny".

Istnieje wiele gotchyas w Javie, gdy zaczynasz używać statyki, które nie zawsze są od razu oczywiste. Na przykład, jeśli masz uruchomione dwie kopie programu czy w tej samej maszynie wirtualnej zmienią wartość zmiennej statycznej i zmienią jej stan? Albo co się stanie, gdy rozszerzysz klasę, czy możesz nadpisać statyczny członek? Czy Twojej maszynie wirtualnej kończy się pamięć, ponieważ masz szaloną liczbę statyk i tej pamięci nie można odzyskać dla innych potrzebnych obiektów instancji?

Czas Życia Obiektu: Dodatkowo statyka ma czas życia odpowiadający całemu uruchomieniu programu. Oznacza to, że nawet po zakończeniu korzystania z Klasa, pamięć ze wszystkich tych zmiennych statycznych nie może być pobierana ze śmieci. Jeśli zamiast tego, na przykład, zmienisz swoje zmienne niestatyczne, a w funkcji main() utworzysz pojedynczą instancję swojej klasy, a następnie poprosisz klasę o wykonanie określonej funkcji 10 000 razy, po wykonaniu tych 10 000 wywołań i usunięciu odniesień do pojedynczej instancji, wszystkie Twoje zmienne statyczne mogą zostać usunięte i ponownie użyte.

Zapobiega pewnemu ponownemu użyciu: Również statyczne metody nie mogą być używane do implementacji interfejsu, więc metody statyczne mogą uniemożliwić korzystanie z pewnych obiektowych funkcji.

Inne Opcje: Jeśli wydajność jest twoim głównym zmartwieniem, mogą istnieć inne lepsze sposoby rozwiązania problemu prędkości niż rozważanie tylko korzyści wywołania, które jest zwykle szybsze niż tworzenie. Zastanów się, czy modyfikatory przejściowe lub lotne są potrzebne w dowolnym miejscu. Aby zachować możliwość inlinowania, metoda może być oznaczona jako finał zamiast statyki. Parametry metody i inne zmienne mogą być oznaczone jako ostateczne, aby umożliwić pewną optymalizację kompilatora w oparciu o założenia co może zmienić te zmienne. Obiekt instancji może być ponownie użyty wielokrotnie, zamiast tworzyć za każdym razem nową instancję. Mogą być przełączniki optymalizacji compliler, które powinny być włączone dla aplikacji w ogóle. Być może projekt powinien być tak skonfigurowany, aby 10 000 uruchomień mogło być wielowątkowe i korzystać z wielu procesorów rdzenie. Jeśli przenośność nie jest problemem, może natywna metoda zapewni Ci lepszą szybkość niż Twoja statyka.

Jeśli z jakiegoś powodu nie chcesz mieć wielu kopii obiektu, singleton design pattern , ma zalety nad obiektami statycznymi, takie jak bezpieczeństwo wątków (zakładając, że Twój singleton jest dobrze zakodowany), pozwalając na leniwą inicjalizację, gwarantując, że obiekt został prawidłowo zainicjowany, gdy jest używany, podklasowanie, zalety w testowaniu i refaktoryzacji kodu, a nie wspomnij, że jeśli w pewnym momencie zmienisz zdanie na temat potrzeby tylko jednej instancji obiektu, o wiele łatwiej jest usunąć kod, aby zapobiec duplikatom wystąpień, niż refaktorować cały kod zmiennej statycznej, aby użyć zmiennych wystąpień. Musiałem to zrobić wcześniej, to nie jest zabawne, a w końcu musisz edytować o wiele więcej klas, co zwiększa ryzyko wprowadzenia nowych bugs...so znacznie lepiej ustawić rzeczy "prawo" za pierwszym razem, nawet jeśli wydaje się, że ma swoje wady. For me, the przeróbka wymagana, jeśli zdecydujesz się na dalszą drogę, potrzebujesz wielu kopii czegoś, jest prawdopodobnie jednym z najbardziej przekonujących powodów, aby używać statyki tak rzadko, jak to możliwe. I dlatego też nie zgodziłbym się z Twoim stwierdzeniem, że statyka zmniejsza wzajemne zależności, myślę, że skończysz z kodem, który jest bardziej sprzężony, jeśli masz dużo statyki, do której można uzyskać bezpośredni dostęp, a nie obiekt, który "wie, jak coś zrobić" na sobie.

 239
Author: Jessica Brown,
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-03-07 19:31:39

Zło jest terminem subiektywnym.

Nie kontrolujesz statyki pod względem tworzenia i niszczenia. Żyją na polecenie programu załadunku i rozładunku.

Ponieważ statyki żyją w jednej przestrzeni, wszystkie wątki, które chcą z nich korzystać, muszą przejść kontrolę dostępu, którą musisz zarządzać. Oznacza to, że programy są bardziej powiązane, a zmiana ta jest trudniejsza do przewidzenia i zarządzania(jak mówi J Skeet). Prowadzi to do problemów z izolacją wpływu zmiany, a tym samym wpływa na sposób testowania jest zarządzany.

To są dwa główne problemy, które mam z nimi.

 83
Author: Preet Sangha,
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-08-11 13:25:26

Nie. Państwa globalne nie są złe samo w sobie. Ale musimy zobaczyć Twój kod, aby sprawdzić, czy użyłeś go poprawnie. Jest całkiem możliwe, że nowicjusz nadużywa państw globalnych; tak jak nadużywa każdej funkcji językowej.

Państwa globalne są absolutną koniecznością. Nie możemy uniknąć państw globalnych. Nie możemy uniknąć rozumowania na temat państw globalnych. - Jeśli chcemy zrozumieć naszą semantykę aplikacji. Ludzie, którzy próbują pozbyć się państw globalnych dla tego celu, nieuchronnie kończą ze znacznie bardziej złożonym systemem-a państwa globalne wciąż tam są, sprytnie / idiotycznie zamaskowane pod wieloma warstwami indirections; i nadal musimy myśleć o stanach globalnych, po rozpakowaniu wszystkich indirections.

Jak ludzie Wiosny, którzy obficie deklarują Stany globalne w xml i myślą, że są lepsze.

@Jon Skeet if I create a new instance of an object teraz masz dwie rzeczy do rozumowania - stan wewnątrz obiektu i stan środowiska hostującego obiekt.

 52
Author: irreputable,
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-08-11 14:34:04

Istnieją 2 główne problemy ze zmiennymi statycznymi:

  • bezpieczeństwo wątków - zasoby statyczne z definicji nie są bezpieczne dla wątków
  • Implicity kodu-nie wiesz, kiedy statyczna zmienna jest instancjonowana i czy będzie instancjonowana przed inną zmienną statyczną
 28
Author: sternr,
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-08-11 13:19:51

Jeśli używasz słowa kluczowego "static" bez słowa kluczowego "final", powinien to być sygnał do uważnego rozważenia projektu. Nawet obecność "finału" nie jest swobodną przepustką, ponieważ zmienny statyczny obiekt końcowy może być równie niebezpieczny.

Szacowałbym gdzieś około 85% czasu, kiedy widzę "statyczny" bez "ostatecznego", to jest złe. Często znajdę dziwne obejścia, aby zamaskować lub ukryć te problemy.

Proszę nie tworzyć statycznych mutabli. Zwłaszcza Kolekcje. Ogólnie rzecz biorąc, Kolekcje powinny być inicjowane, gdy ich zawierający obiekt jest inicjowany i powinny być zaprojektowane tak, aby były resetowane lub zapomniane, gdy ich zawierający obiekt jest zapomniany.

Używanie statyki może stworzyć bardzo subtelne błędy, które spowodują, że inżynierowie będą cierpieć przez wiele dni. Wiem, bo stworzyłem i polowałem na te robaki.

Jeśli chcesz uzyskać więcej szczegółów, przeczytaj dalej ...

Dlaczego Nie Użyć Statyki?

Jest wiele problemów ze statyką, w tym pisaniem i wykonywaniem testów, a także subtelnymi błędami, które nie są od razu oczywiste.

Kod, który opiera się na obiektach statycznych, nie może być łatwo testowany jednostkowo, a statyka nie może być łatwo wyśmiewana (Zwykle).

Jeśli używasz statyki, nie jest możliwe Zamiana implementacji klasy w celu przetestowania komponentów wyższego poziomu. Na przykład wyobraź sobie statyczny CustomerDAO, który zwraca obiekty klienta ładowane z bazy danych. Teraz mam zajęcia CustomerFilter, który potrzebuje dostępu do niektórych obiektów klienta. Jeśli CustomerDAO jest statyczne, nie mogę napisać testu dla CustomerFilter bez uprzedniej inicjalizacji mojej bazy danych i wypełnienia użytecznych informacji.

I populacji bazy danych i inicjalizacji zajmuje dużo czasu. Z mojego doświadczenia wynika, że struktura inicjalizacji DB zmieni się z czasem, co oznacza, że dane będą się przekształcać, a testy mogą się zepsuć. IE, wyobraź sobie, że Klient 1 był kiedyś VIP, ale zmienił się Framework inicjalizacji DB, a teraz Klient 1 nie jest już VIP, ale twój test został ciężko zakodowany, aby załadować Klienta 1 ...

Lepszym podejściem jest utworzenie instancji CustomerDAO i przekazanie jej do CustomerFilter po jego zbudowaniu. (Jeszcze lepszym podejściem byłoby użycie sprężyny lub innej inwersji RAM sterowania.

Gdy to zrobisz, możesz szybko wyśmiać lub wymazać alternatywne DAO w swoim CustomerFilterTest, pozwalając Ci mieć większą kontrolę nad testem,

Bez statycznego DAO, test będzie szybsze (bez inicjalizacji db) i bardziej niezawodne (ponieważ nie zawiedzie, gdy zmieni się kod inicjalizacji db). Na przykład, w tym przypadku zapewnienie Klient 1 jest i zawsze będzie VIP, jeśli chodzi o test.

Wykonywanie Testów

Statyka powoduje prawdziwy problem podczas jednoczesnego uruchamiania pakietów testów jednostkowych(na przykład z serwerem Continuous Integration). Wyobraź sobie statyczną mapę obiektów gniazd sieciowych, która pozostaje otwarta od jednego testu do drugiego. Na pierwszy test może otworzyć gniazdo na porcie 8080, ale zapomniałeś wyczyścić mapę, gdy test zostanie zburzony. Teraz, gdy uruchamia się drugi test, prawdopodobnie zawiesi się, gdy próbuje utworzyć nowe gniazdo dla portu 8080, ponieważ port jest nadal zajęty. Wyobraź sobie również, że odwołania do gniazd w Twojej kolekcji statycznej nie są usuwane i (z wyjątkiem WeakHashMap) nigdy nie kwalifikują się do usunięcia śmieci, powodując wyciek pamięci.

Jest to zbyt uogólniony przykład, ale w duże systemy, ten problem zdarza się cały czas. Ludzie nie myślą o testach jednostkowych uruchamiających i zatrzymujących swoje oprogramowanie wielokrotnie w tym samym JVM, ale jest to dobry test projektu oprogramowania, a jeśli masz aspiracje do wysokiej dostępności, musisz być tego świadomy.

Te problemy często pojawiają się w obiektach frameworku, na przykład w dostępie do bazy danych, buforowaniu, wysyłaniu wiadomości i rejestrowaniu warstw. Jeśli używasz Java EE lub jakiegoś najlepszego frameworka, prawdopodobnie zarządzaj wieloma z nich, ale jeśli tak jak ja masz do czynienia ze starszym systemem, możesz mieć wiele niestandardowych frameworków, aby uzyskać dostęp do tych warstw.

Jeśli konfiguracja systemu, która ma zastosowanie do tych komponentów frameworku, zmienia się między testami jednostkowymi, a framework testu jednostkowego nie zburzy ani nie odbuduje komponentów, zmiany te nie mogą wejść w życie, a gdy test opiera się na tych zmianach, nie powiedzie się.

Nawet komponenty inne niż framework podlegają temu problemowi. Wyobraź sobie statyczną mapę o nazwie OpenOrders. Piszesz jeden test, który tworzy kilka otwartych zleceń i sprawdzasz, czy wszystkie są we właściwym stanie, a następnie test się kończy. Inny programista pisze drugi test, który umieszcza potrzebne zamówienia na mapie OpenOrders, a następnie zapewnia, że liczba zamówień jest dokładna. Uruchamiane pojedynczo, te testy zdałyby oba, ale gdy biegną razem w pakiecie, nie powiedzą.

Gorzej, niepowodzenie może być oparte na kolejności, w jakiej testy były uciekaj.

W tym przypadku, unikając statyki, unikasz ryzyka utrzymywania się danych między instancjami testowymi, zapewniając lepszą niezawodność testów.

Subtelne Błędy

Jeśli pracujesz w środowisku wysokiej dostępności lub w dowolnym miejscu, w którym wątki mogą być uruchamiane i zatrzymywane, ta sama troska o Pakiety testów jednostkowych może mieć zastosowanie również wtedy, gdy twój kod jest uruchomiony na produkcji.

Gdy mamy do czynienia z wątkami, zamiast używać statycznego obiektu do przechowywania danych, to lepiej jest użyć obiektu zainicjowanego podczas fazy uruchamiania wątku. W ten sposób za każdym razem, gdy wątek jest uruchamiany, tworzy się nową instancję obiektu (z potencjalnie nową konfiguracją), a dane z jednej instancji wątku nie przechodzą do następnej instancji.

Gdy wątek umiera, obiekt statyczny nie jest resetowany ani zbierany. Wyobraź sobie, że masz wątek o nazwie "EmailCustomers", a po jego uruchomieniu zapełnia statyczną kolekcję ciągów listą adresów e-mail, a następnie rozpoczyna wysyłanie e-maili do każdego z tych adresów. Powiedzmy, że wątek został w jakiś sposób przerwany lub anulowany, więc struktura wysokiej dostępności uruchamia ponownie wątek. Następnie, gdy wątek się uruchamia, przeładowuje listę klientów. Ale ponieważ kolekcja jest statyczna, może zachować listę adresów e-mail z poprzedniej kolekcji. Teraz niektórzy klienci mogą otrzymywać duplikaty wiadomości e-mail.

An: Static Final

Użycie" static final " jest skutecznie Java odpowiednik C #define, choć istnieją techniczne różnice w implementacji. C / C++ #define jest zamieniane z kodu przez pre-procesor, przed kompilacją. Java "static final" zakończy się rezydentem pamięci na stosie. W ten sposób jest bardziej podobna do zmiennej "static const" w C++ niż do #define.

Podsumowanie

Mam nadzieję, że pomoże to wyjaśnić kilka podstawowych powodów, dla których statyka jest problematyczna. Jeśli używasz nowoczesnego frameworka Java podobnie jak Java EE, Spring itp., możesz nie napotkać wielu z tych sytuacji, ale jeśli pracujesz z dużą ilością starszego kodu, mogą one stać się znacznie częstsze.

 24
Author: JBCP,
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-05-08 23:05:09

Ponieważ nikt* o tym nie wspomniał: zmienne statyczne mogą cię zaskoczyć, jeśli masz wiele wątków do odczytu i zapisu zmiennej statycznej. Jest to powszechne w aplikacjach internetowych (np. ASP.NET) i może powodować dość szalone błędy. Na przykład, jeśli masz zmienną statyczną, która jest aktualizowana przez stronę, a strona jest żądana przez dwie osoby w "prawie tym samym czasie", jeden użytkownik może uzyskać wynik oczekiwany przez drugiego użytkownika, lub gorzej.

Statyka zmniejsz wzajemne zależności od innych części kodu. Mogą działać jako doskonałe posiadacze państwa

Mam nadzieję, że jesteś gotowy do używania zamków i radzenia sobie ze sporami.

*właściwie, Preet Sangha wspomniała o tym.

 13
Author: Justin M. Keyes,
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:55:10

Gdybym musiał wykonać 10 000 wywołań do funkcji w klasie, byłbym cieszę się, że metoda staje się statyczna i używa prostego klasy.methodCall() na nim zamiast zaśmiecać pamięć 10,000 klasy, prawda?

Trzeba zrównoważyć potrzebę enkapsulacji danych w obiekt ze stanem, a potrzebę prostego obliczenia wyniku funkcji na niektórych danych.

Ponadto statyka zmniejsza wzajemne zależności od Inne części kodeksu.

Tak samo enkapsulacja. W dużych aplikacjach statyka ma tendencję do tworzenia kodu spaghetti i nie pozwala łatwo na refaktoryzację lub testowanie.

Inne odpowiedzi również dostarczają dobrych powodów przeciwko nadmiernemu stosowaniu statyki.

 12
Author: Jérôme Verstrynge,
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-08-11 14:43:40

Zmienne statyczne są ogólnie uważane za złe, ponieważ reprezentują stan globalny i dlatego są znacznie trudniejsze do rozumowania. W szczególności łamią one założenia programowania obiektowego. W programowaniu obiektowym każdy obiekt ma swój własny stan, reprezentowany przez zmienne instancyjne (niestatyczne). Zmienne statyczne reprezentują stan między instancjami, co może być znacznie trudniejsze do testowania jednostkowego. Dzieje się tak głównie dlatego, że trudniej jest wyodrębnić zmiany do zmienne statyczne do jednego testu.

To powiedziawszy, ważne jest, aby dokonać rozróżnienia między zwykłymi zmiennymi statycznymi (ogólnie uważanymi za złe), a ostatecznymi zmiennymi statycznymi (aka stałymi; nie tak źle).

 10
Author: Jack Edmonds,
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-08-16 18:56:44

Podsumowanie kilku podstawowych zalet i wad używania metod statycznych w Javie:

Zalety:

  1. dostępny globalnie, tzn. nie związany z żadną konkretną instancją obiektu.
  2. jedna instancja na JVM.
  3. można uzyskać, używając nazwy klasy (nie wymaga obiektu).
  4. zawiera jedną wartość mającą zastosowanie do wszystkich instancji.
  5. ładuje się przy starcie JVM i umiera po wyłączeniu JVM.
  6. nie modyfikują stan obiektu.

Wady:

  1. członkowie statyczni są zawsze częścią pamięci, są w użyciu lub nie.
  2. nie można kontrolować tworzenia i niszczenia zmiennej statycznej. Użytecznie zostały utworzone podczas ładowania programu i zniszczone podczas rozładowywania programu (lub gdy JVM wyłącza się).
  3. możesz uczynić wątek statyczny bezpiecznym za pomocą synchronize, ale potrzebujesz dodatkowych wysiłków.
  4. Jeśli jeden wątek zmienia wartość zmiennej statycznej to może ewentualnie złamać funkcjonalność innych wątków.
  5. musisz znać "static" przed użyciem.
  6. nie można nadpisać metod statycznych.
  7. Serializacja nie działa z nimi dobrze.
  8. nie uczestniczą w polimorfizmie czasowym.
  9. występuje problem z pamięcią (w pewnym stopniu, ale chyba niewiele), jeśli używana jest duża liczba statycznych zmiennych/metod. Ponieważ nie będą GC dopóki program się nie skończy.
  10. statyczne metody są trudne do przetestowania też.
 10
Author: Aftab Virtual,
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
2016-09-22 10:41:56

Moim zdaniem prawie nigdy nie chodzi o wydajność, chodzi o design. Nie uważam, że używanie metod statycznych jest złe, jako związane z używaniem zmiennych statycznych(ale chyba rzeczywiście mówisz o wywołaniach metod).

Chodzi po prostu o to, jak wyizolować logikę i dać jej dobre miejsce. Czasami uzasadnia to stosowanie metod statycznych, których java.lang.Math jest dobrym przykładem. Myślę, że kiedy nazwiesz większość swoich klas XxxUtil lub Xxxhelper, lepiej przemyśl swój projekt.

 9
Author: M Platvoet,
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-08-11 13:23:14

Można zasugerować, że w większości przypadków, gdy używasz zmiennej statycznej, naprawdę chcesz używać singleton pattern.

Problem Stanów globalnych polega na tym, że czasami to, co ma sens jako globalne w prostszym kontekście, musi być nieco bardziej elastyczne w kontekście praktycznym, i to jest, gdzie wzór Singletona staje się użyteczny.

 6
Author: Charles Goodwin,
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-08-11 15:05:57

Jeszcze jeden powód: kruchość.

Jeśli masz klasę, większość ludzi oczekuje, że będzie w stanie ją stworzyć i używać do woli.

Można udokumentować, że tak nie jest, lub zabezpieczyć przed tym (singleton/wzór fabryczny) - ale to dodatkowa praca, a co za tym idzie dodatkowy koszt. Nawet wtedy, w dużej firmie, są szanse, że ktoś spróbuje w pewnym momencie wykorzystać Twoją klasę, nie zwracając w pełni uwagi na wszystkie miłe komentarze lub fabrykę.

Jeśli używasz zmiennych statycznych a lot, to się zepsuje. Robaki są drogie.

Między a .0001% poprawa wydajności i solidność do zmiany przez potencjalnie bezmyślnych programistów, w wielu przypadkach solidność jest dobrym wyborem.

 5
Author: ptyx,
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-08-11 23:42:02

Właśnie podsumowałem niektóre punkty zawarte w odpowiedziach. Jeśli znajdziesz coś złego, proszę nie krępuj się to poprawić.

Skalowanie: mamy dokładnie jedną instancję zmiennej statycznej na JVM. Załóżmy, że rozwijamy system zarządzania biblioteką i zdecydowaliśmy się umieścić nazwę książki jako zmienną statyczną, ponieważ na książkę przypada tylko jedna. Ale jeśli system rośnie i używamy wielu JVMs to nie mamy sposobu, aby dowiedzieć się, którą książkę mamy do czynienia z?

Thread-Safety: zarówno zmienna instancji, jak i zmienna statyczna muszą być kontrolowane, gdy są używane w środowisku wielowątkowym. Ale w przypadku zmiennej instancyjnej nie wymaga ochrony, chyba że jest jawnie współdzielona między wątkami, ale w przypadku zmiennej statycznej jest zawsze współdzielona przez wszystkie wątki w procesie.

Testowanie: chociaż testowalna konstrukcja nie równa się dobrej konstrukcji, ale rzadko będziemy obserwować dobry projekt, który nie jest testowalny. Jako zmienne statyczne reprezentują stan globalny i bardzo trudno je przetestować.

Rozumowanie o stanie: Jeśli stworzę nową instancję klasy, to możemy wnioskować o stanie tej instancji, ale jeśli ma ona zmienne statyczne, to może być w dowolnym stanie. Dlaczego? Ponieważ możliwe jest, że zmienna statyczna została zmodyfikowana przez inną instancję, ponieważ zmienna statyczna jest współdzielona między instancjami.

Serializacja: serializacja również nie działa dobrze z nimi.

Tworzenie i niszczenie: Tworzenie i niszczenie zmiennych statycznych nie może być kontrolowane. Zwykle są one tworzone i niszczone w czasie załadunku i rozładunku programu. Oznacza to, że są złe dla zarządzania pamięcią, a także sumują Czas inicjalizacji przy starcie.

A jeśli naprawdę ich potrzebujemy?

Ale czasami możemy mieć ich prawdziwą potrzebę. Jeśli naprawdę odczuwamy potrzebę wielu zmiennych statycznych, które są współdzielone przez aplikacja następnie jedną z opcji jest wykorzystanie Singleton Design pattern, który będzie miał wszystkie te zmienne. Albo możemy stworzyć jakiś obiekt, który będzie posiadał zmienną statyczną i może być przekazywany.

Również jeżeli zmienna statyczna jest oznaczona jako ostateczna, staje się stała i nie można zmienić wartości przypisanej do niej raz. Oznacza to, że uchroni nas przed wszystkimi problemami, z jakimi borykamy się ze względu na jego zmienność.

 5
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
2016-05-20 07:19:16

Zmienne statyczne przede wszystkim stwarzają problem z bezpieczeństwem danych (każda zmiana czasu, każdy może się zmienić, bezpośredni dostęp bez obiektu, itp.)

Aby uzyskać więcej informacji przeczytaj to Dzięki.

 4
Author: Anuj Patel,
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-08-11 13:22:40

dla mnie statyczne zmienne są wygodniejsze w użyciu. I zakładam, że są one również efektywne (Proszę mnie poprawić, jeśli się mylę), ponieważ gdybym miał wykonać 10 000 wywołań do funkcji w klasie, byłbym zadowolony, aby metoda stała i używała prostej klasy.methodCall() zamiast zaśmiecać pamięć 10 000 instancji klasy, prawda?

Widzę, co myślisz, ale prosty wzór Singletona zrobi to samo bez konieczności tworzenia 10 000 obiektów.

Metody statyczne mogą być stosowane, ale tylko dla funkcji, które są związane z domeną obiektu i nie potrzebują ani nie używają wewnętrznych właściwości obiektu.

Ex:

public class WaterContainer {
    private int size;
    private int brand;
    ...etc

    public static int convertToGallon(int liters)...

    public static int convertToLiters(int gallon)...

}
 4
Author: Cygnusx1,
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-08-11 13:39:47

Kwestia "statyki jako zła" jest bardziej kwestią globalnego Państwa. Odpowiedni czas, aby zmienna była statyczna, jest taki, gdy nigdy nie ma więcej niż jednego stanu; czyli narzędzia, które powinny być dostępne przez cały framework i zawsze zwracają te same wyniki dla tych samych wywołań metod, nigdy nie są " złe " jak statyka. Co do Twojego komentarza:

Uważam, że statyczne zmienne są wygodniejsze w użyciu. I zakładam, że też są wydajne

Statyka to idealny i efektywny wybór dla zmiennych / klas, które nigdy się nie zmieniają .

Problemem stanu globalnego jest nieodłączna niespójność, którą może on stworzyć. Dokumentacja testów jednostkowych często rozwiązuje ten problem, ponieważ za każdym razem, gdy istnieje stan globalny, do którego dostęp może uzyskać więcej niż wiele niepowiązanych obiektów, testy jednostkowe będą niekompletne, a nie "jednostkowe" ziarniste. Jak wspomniano w tym artykule o globalnym stanie i singletonach , jeśli obiekt A i B nie są ze sobą powiązane (ponieważ w jednym nie jest wyraźnie podane odniesienie do innego), wtedy A nie powinien być w stanie wpłynąć na stan B.

Istnieją pewne wyjątki od zakazu globalnego stanu w dobrym kodzie, takie jak zegar. Czas jest globalny i-w pewnym sensie-zmienia stan obiektów bez zakodowanej relacji.

 4
Author: Bryan Agee,
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-08-11 23:07:46

Wydaje mi się, że pytasz o zmienne statyczne, ale również wskazujesz metody statyczne w swoich przykładach.

Zmienne statyczne nie są złe - mają swoją adopcję jako zmienne globalne, takie jak stałe w większości przypadków połączone z ostatecznym modyfikatorem, ale jak powiedział, nie nadużywaj ich.

Metody statyczne aka metoda użytkowa. Zazwyczaj nie jest to zła praktyka, aby ich używać, ale głównym problemem jest to, że mogą one [5]}utrudniać {6]} testowanie.

Jako przykład świetnej Javy projekt, który wykorzystuje wiele statyki i robi to dobrze, proszę spojrzeć na grać! framework . Istnieje równieżdyskusja o tym w SO.

Statyczne zmienne / metody połączone ze statycznym importem są również szeroko stosowane w bibliotekach ułatwiających programowanie deklaratywne w Javie, takich jak: make it easy lub Hamcrest. Nie byłoby to możliwe bez wielu zmiennych statycznych i metod.

Więc zmienne statyczne (i metody) są dobre, ale używać ich mądrze!

 4
Author: cetnar,
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:47:29

Mój $.02 jest to, że kilka z tych Odpowiedzi są mylące problem, zamiast mówić "statyki są złe" myślę, że lepiej mówić o zasięgu I instancji.

Powiedziałbym, że statyczna jest zmienną "klasową" - reprezentuje wartość współdzieloną przez wszystkie instancje tej klasy. Zazwyczaj powinien być również tak ustawiony (protected lub private to class and its instances).

Jeśli planujesz umieścić wokół niego zachowanie na poziomie klasy i wystawić je na działanie innego kodu, wtedy singleton może być lepszym rozwiązaniem do wspierania zmian w przyszłości (jak zasugerował @ Jessica). Dzieje się tak, ponieważ możesz używać interfejsów na poziomie instancji/singleton w sposób, którego nie możesz użyć na poziomie klasy - w szczególności dziedziczenia.

Kilka przemyśleń na temat tego, dlaczego myślę, że niektóre aspekty w innych odpowiedziach nie są podstawą do pytania...

Statyka nie jest "globalna". W Javie zakres jest kontrolowany oddzielnie od statycznego / instancji.

Współbieżność jest nie mniej niebezpieczne dla statyki niż metody instancji. To nadal państwo musi być chronione. Oczywiście możesz mieć 1000 wystąpień ze zmienną instancyjną i tylko jedną zmienną statyczną, ale jeśli kod do którego dostęp nie jest napisany w bezpieczny dla wątku sposób, nadal masz przesrane - może to potrwać trochę dłużej, zanim go zrealizujesz.

Zarządzanie cyklem życia jest interesującym argumentem, ale myślę, że jest mniej ważny. Nie rozumiem, dlaczego trudno jest zarządzać parą metod klasowych podobnie jak INIT ()/clear () niż tworzenie i niszczenie instancji singleton. W rzeczywistości, niektórzy mogą powiedzieć singleton jest trochę bardziej skomplikowane ze względu na GC.

PS, jeśli chodzi o Smalltalk, wiele jego dialektów ma zmienne klasowe, ale w Smalltalk klasy są rzeczywiście instancjami Metaclass, więc są naprawdę zmiennymi na instancji Metaclass. Mimo to zastosowałbym tę samą zasadę. Jeśli są one używane do współdzielenia stanu między instancjami, to ok. Jeśli wspierają funkcjonalność publiczna powinieneś spojrzeć na Singleton. Tęsknie za Smalltalkiem....

 4
Author: studgeek,
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-07-15 15:19:57

Nie ma nic złego w statycznych zmiennych per se. Tylko składnia Javy jest zepsuta. Każda klasa Javy w rzeczywistości definiuje dwie struktury - obiekt singleton, który zawiera statyczne zmienne, oraz instancję. Definiowanie obu w tym samym bloku źródłowym jest czystym złem i skutkuje kodem, który jest trudny do odczytania. Scala zrobił to dobrze.

 4
Author: Zdeněk Pavlas,
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-02-12 12:33:51

A) powód o programach.

Jeśli masz program o małym lub średnim rozmiarze, gdzie zmienna statyczna Global.foo jest dostępne, wywołanie do niego zwykle przychodzi znikąd - nie ma ścieżki, a zatem nie ma osi czasu, jak zmienna dociera do miejsca, w którym jest używana. Skąd mam wiedzieć, kto ustawił jego rzeczywistą wartość? Skąd mam wiedzieć, co się stanie, jeśli zmienię to teraz? Mam grep na całym źródle, aby zebrać wszystkie dostępy, aby wiedzieć, co się dzieje.

Jeśli wiesz jak go używasz, ponieważ właśnie napisałeś kod, problem jest niewidoczny, ale jeśli spróbujesz zrozumieć obcy kod, zrozumiesz.

B) czy naprawdę potrzebujesz tylko jednego?

Zmienne statyczne często uniemożliwiają uruchamianie wielu programów tego samego rodzaju w tym samym JVM o różnych wartościach. Często nie przewidujesz zastosowań, w których więcej niż jedna instancja Twojego programu jest przydatna, ale jeśli ewoluuje lub jest przydatna dla innych, mogą doświadczyć sytuacji, w których chcesz uruchomić więcej niż jedną instancję programu.

Tylko mniej lub bardziej bezużyteczny kod, który nie będzie używany przez wiele osób przez dłuższy czas w intensywny sposób, może dobrze pasować do zmiennych statycznych.

 3
Author: user unknown,
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-08-11 19:49:18

W Twoim poście są dwa główne pytania.

Po pierwsze, o zmiennych statycznych. Zmienne statyczne są całkowicie niezauważalne i można ich łatwo uniknąć. W językach OOP ogólnie, a szczególnie w Javie, parametry funkcji są sortowane przez odniesienie, to znaczy, jeśli przekazujesz obiekt do funkcji, przekazujesz wskaźnik do obiektu, więc nie musisz definiować zmiennych statycznych, ponieważ możesz przekazać wskaźnik do obiektu do dowolnego zakresu, który potrzebuje tych informacji. Nawet jeśli oznacza to, że yo wypełni twoją pamięć wskaźnikami, nie będzie to konieczne, ponieważ rzeczywiste systemy stronicowania pamięci są zoptymalizowane do obsługi tego, i będą utrzymywać w pamięci strony, do których odnoszą się wskaźniki przekazane do nowego zakresu; użycie zmiennych statycznych może spowodować, że system załaduje stronę pamięci, gdzie są przechowywane, gdy trzeba będzie uzyskać do nich dostęp (stanie się tak, jeśli strona nie była dostępna przez długi czas). Dobra praktyka aby umieścić wszystkie statyczne stuf razem w niektórych małych "clases konfiguracji", to zapewni system umieszcza to wszystko w tej samej stronie pamięci.

Po drugie, o metodach statycznych. Metody statyczne nie są takie złe, ale mogą szybko zmniejszyć wydajność. Na przykład, pomyśl o metodzie, która porównuje dwa obiekty klasy i zwraca wartość wskazującą, który z obiektów jest większy (tipical comparison method) ta metoda może być statyczna lub nie, ale podczas wywoływania jej postać niestatyczna będzie być bardziej wydajne, ponieważ będzie musiał rozwiązać tylko dwa odwołania (po jednym dla każdego obiektu) twarzą do trzech odwołań, które będą musiały rozwiązać statyczną wersję tej samej metody (jeden dla klasy plus dwa, po jednym dla każdego obiektu). Ale jak mówię, nie jest tak źle, jeśli przyjrzymy się klasie matematyki, możemy znaleźć wiele funkcji matematycznych zdefiniowanych jako metody statyczne. Jest to naprawdę bardziej efektywne niż umieszczenie wszystkich tych metod w klasie definiującej liczby, ponieważ większość z nich jest rzadko używana włączenie ich wszystkich do klasy number spowoduje, że klasa będzie bardzo złożona i pochłonie wiele zasobów.

W konkluzji: unikaj użycia zmiennych statycznych i znajdź właściwą równowagę wydajności w przypadku metod statycznych lub niestatycznych.

PS: przepraszam za mój angielski.

 3
Author: jrodriguez,
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-01-05 12:18:39

Wszystko (może:) ma swój cel, jeśli masz kilka wątków, które MUSZĄ udostępniać / buforować DANE, a także całą dostępną pamięć (więc nie dzielisz się na konteksty w ramach jednego JVM) statyczne jest najlepszym wyborem

-> oczywiście możesz wymusić tylko jeden przypadek, ale dlaczego?
część komentarzy w tym wątku uważam za złe, a nie statykę;)

 3
Author: tomasb,
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 17:14:04

Wszystkie powyższe odpowiedzi pokazują, dlaczego statyka jest zła. Powodem, dla którego są źli jest to, że daje fałszywe wrażenie, że piszesz kod zorientowany obiektowo, podczas gdy w rzeczywistości nim nie jesteś. To zwykłe zło.

 2
Author: blockhead,
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-08-11 16:47:37

Zmienne statyczne nie są dobre ani złe. Reprezentują one atrybuty opisujące całą klasę, A nie konkretną instancję. Jeśli musisz mieć licznik dla wszystkich instancji danej klasy, statyczna zmienna byłaby właściwym miejscem do przechowywania wartości.

Problemy pojawiają się podczas próby użycia zmiennych statycznych do przechowywania wartości związanych z wystąpieniem.

 2
Author: Andres,
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-04-27 09:25:30

Jest tu mnóstwo dobrych odpowiedzi, dodając do tego,

Pamięć: Zmienne statyczne są aktywne tak długo, jak długo trwa Loader klasy [ogólnie do śmierci maszyny wirtualnej], ale jest to tylko w przypadku obiektów/odniesień masowych przechowywanych jako statyczne.

Modularyzacja: rozważmy pojęcia takie jak IOC, dependencyInjection, proxy itp.. Wszystkie są całkowicie przeciwne ściśle powiązanym / statycznym implementacjom.

Inne przekręty: bezpieczeństwo wątku, Testowalność

 1
Author: Sankarganesh Eswaran,
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
2016-01-31 11:38:41

Pomyśl, że jeśli masz aplikację z wieloma użytkownikami i masz zdefiniowaną formę statyczną, to każdy użytkownik będzie modyfikował również wszystkie inne formy innych użytkowników.

 0
Author: seinta,
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-08-07 07:51:49

Myślę, że nadmierne użycie globalnych zmiennych ze statycznym słowem kluczowym doprowadzi również do wycieku pamięci w pewnym momencie wystąpienia w aplikacji

 0
Author: Rahul Anand,
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-10-11 12:13:37