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


635

Jestem programistą Java, który jest nowy w świecie korporacyjnym. Ostatnio opracowałem aplikację wykorzystującą Groovy i Java. Cały kod, który napisałem, używał całkiem niezłej liczby statyki. Starszy dział techniczny poprosił mnie o ograniczenie liczby używanych statyki. Oszukałem to samo i stwierdziłem, że wielu programistów jest przeciwnych stosowaniu zmiennych statycznych.

Uważam, że zmienne statyczne są wygodniejsze w użyciu. Zakładam też, że są one również wydajne (proszę mnie poprawić, jeśli się mylę), ponieważ gdybym musiał wykonać 10 000 wywołań funkcji w klasie, chętnie uczynię metodę statyczną i użyję prostej metody Class.methodCall()zamiast zaśmiecanie pamięci 10 000 wystąpień klasy, prawda?

Ponadto statyka zmniejsza wzajemne zależności od innych części kodu. Mogą działać jako posiadacze doskonałego stanu. Dodając do tego, stwierdzam, że statyka jest szeroko implementowana w niektórych językach, takich jak Smalltalk i Scala . Dlaczego więc ucisk na statykę jest powszechny wśród programistów (szczególnie w świecie Java)?

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


43
Żeby powiedzieć, nie ma żadnych zmiennych statycznych ani metod na Smalltalk lub Scali, właśnie dlatego, że metody statyczne i zmienne są sprzeczne z zasadami OOP.
Maurício Linhares,

87
Przynajmniej jedno wypowiedź jest dość ciekawa: „statyka zmniejsza wzajemne zależności między pozostałymi częściami kodu”. Zasadniczo zaostrzają zależności. Kod, w którym wykonywane jest wywołanie, jest ściśle związany z wywoływanym kodem. Brak abstrakcji pomiędzy, bezpośrednia zależność.
Arne Deutsch

11
Dobre pytanie ... więcej o Programmers.SE Masz pytania?
WernerCD

26
Drugi akapit dotyczy zupełnie innego tematu, a mianowicie metod statycznych .
Paul,

8
Programowanie funkcjonalne również marszczy brwi na punkcie stanu globalnego. Jeśli kiedyś (i powinieneś ) dostać się do FP, przygotuj się na porzucenie pojęcia stanu globalnego.
new123456,

Odpowiedzi:


689

Zmienne statyczne reprezentują stan globalny. Jest to trudne do uzasadnienia i trudne do przetestowania: jeśli utworzę nową instancję obiektu, mogę sprawdzić jego nowy stan w testach. Jeśli użyję kodu, który używa zmiennych statycznych, może być w dowolnym stanie - i wszystko może go modyfikować.

Mógłbym kontynuować przez dłuższy czas, ale im większy pomysł, o którym myślę, że im ściślejszy zakres czegoś, tym łatwiej jest uzasadnić. Jesteśmy dobrzy w myśleniu o małych rzeczach, ale trudno jest zrozumieć stan systemu linii milionowej, jeśli nie ma modułowości. Nawiasem mówiąc, dotyczy to wszystkich rzeczy - nie tylko zmiennych statycznych.


57
To ostatnio wydaje się być argumentem, niezależnie od tego, czy kod można przetestować, czy nie. To dość błędne rozumowanie. Argumentem powinien być „dobry projekt” i zwykle dobry projekt można przetestować. Ale nie na odwrót: „Nie mogę tego przetestować, ponieważ musi to być zły projekt”. Nie zrozumcie mnie źle, zgadzam się ogólnie z twoim postem.
M Platvoet,

144
@M Platvoet: Powiedziałbym, że biorąc pod uwagę wybór między dwoma równie ważnymi projektami, testowalny jest lepszy. Możliwość testowania z pewnością nie oznacza bycia dobrze zaprojektowanym, ale rzadko spotykam niesprawdzalne dobre projekty i myślę, że są one wystarczająco rzadkie, że nie mam problemu z uczynieniem z testowania ogólnego wskaźnika przyczyniającego się do dobrego projektu.
Jon Skeet,

9
@M Platvoet - Testowalność wpływa zarówno na łatwość konserwacji, jak i niezawodność, i rozważyłbym te główne czynniki w jakości projektu. Z pewnością nie są to jedyne czynniki, ale IMHO kosztem danego kodu jest kombinacja cykli maszynowych, cykli programowania i cykli użytkownika. Testowalność uderza dwa z tych trzech.
Justin Morgan

5
@M Platvoet - Testowalność ma również wpływ na możliwość ponownego użycia, ponieważ odsprzężona klasa jest zazwyczaj łatwiejsza do ponownego użycia.
TrueWill

13
M Platvoet - Nie zgadzam się z twoim pierwszym komentarzem tutaj. Myślę, że jeśli czegoś nie można przetestować, to jest to zły projekt; ponieważ jeśli nie mogę tego przetestować, nie wiem, czy to działa. Czy kupiłbyś samochód, gdyby sprzedawca powiedział „Konstrukcja tego modelu uniemożliwia jego przetestowanie, więc nie wiem, czy rzeczywiście działa”? Testowalność jest tak istotna dla oprogramowania (jak i samochodów), że kompetentny projekt WYMAGA, aby go uwzględnić.
Dawood ibn Kareem,

277

Nie jest bardzo zorientowany obiektowo: Jednym z powodów, dla których statyka może być uważana za „złą” przez niektórych ludzi jest to, że są oni przeciwni paradygmatowi zorientowanemu obiektowo . W szczególności narusza to zasadę kapsułkowania danych w obiektach (które można rozszerzyć, ukryć informacje itp.). Statyka w sposób, w jaki opisujesz ich użycie, ma zasadniczo na celu wykorzystanie ich jako zmiennej globalnej, aby uniknąć zajmowania się takimi kwestiami, jak zakres. Jednak zmienne globalne są jedną z charakterystycznych cech paradygmatu programowania proceduralnego lub imperatywnego, a nie cechą „dobrego” kodu obiektowego. Nie oznacza to, że paradygmat proceduralny jest zły, ale mam wrażenie, że twój przełożony oczekuje, że napiszesz „dobry kod obiektowy” i naprawdę chcesz napisać „

W Javie jest wiele gotchy, kiedy zaczynasz używać statyki, które nie zawsze są od razu oczywiste. Na przykład, jeśli masz dwie kopie swojego programu działającego na tej samej maszynie wirtualnej, czy będą one niszczały wartość zmiennej statycznej i mieszały się ze sobą? A co się stanie, gdy rozszerzysz klasę, czy możesz przesłonić element statyczny? Czy w maszynie wirtualnej brakuje pamięci, ponieważ masz szaloną liczbę statyki i tej pamięci nie można odzyskać dla innych potrzebnych obiektów instancji?

Czas życia obiektu: Dodatkowo czas życia statyki odpowiada całemu czasowi działania programu. Oznacza to, że nawet po zakończeniu korzystania z klasy pamięć wszystkich tych zmiennych statycznych nie może zostać wyrzucona do pamięci. Jeśli na przykład zamiast tego uczyniłeś zmienne niestatycznymi, a w funkcji main () wykonałeś pojedyncze wystąpienie swojej klasy, a następnie poprosiłeś klasę o wykonanie określonej funkcji 10 000 razy, po wykonaniu tych 10 000 wywołań , a usuniesz odniesienia do pojedynczej instancji, wszystkie zmienne statyczne mogą zostać wyrzucone na śmietnik i ponownie użyte.

Zapobiega ponownemu użyciu: Ponadto metod statycznych nie można używać do implementacji interfejsu, więc metody statyczne mogą uniemożliwić korzystanie z niektórych funkcji obiektowych.

Inne opcje: Jeśli sprawą priorytetową jest wydajność, mogą istnieć inne lepsze sposoby rozwiązania problemu z szybkością niż rozważenie jedynie korzyści z wywołania, która jest zwykle szybsza niż tworzenie. Zastanów się, czy przejściowe lub lotne modyfikatory są potrzebne w dowolnym miejscu. Aby zachować możliwość wstawiania, metodę można oznaczyć jako końcową zamiast statycznej. Parametry metody i inne zmienne można oznaczyć jako końcowe, aby umożliwić pewne optymalizacje kompilatora w oparciu o założenia dotyczące tego, co może zmienić te zmienne. Obiekt instancji może być wielokrotnie użyty wielokrotnie, zamiast tworzenia nowej instancji za każdym razem. Mogą istnieć przełączniki optymalizacji kompilatora, które powinny być ogólnie włączone dla aplikacji. Być może projekt powinien być tak skonfigurowany, aby 10 000 przebiegów mogło być wielowątkowych i korzystać z rdzeni wieloprocesorowych. Jeśli przenośność nie jest

Jeśli z jakiegoś powodu nie chcesz wielu kopii obiektu, wzorzec projektowy singletonu, ma zalety w stosunku do obiektów statycznych, takich jak bezpieczeństwo wątków (zakładając, że singleton jest dobrze zakodowany), umożliwiając leniwą inicjalizację, gwarantując, że obiekt został poprawnie zainicjowany, gdy jest używany, podklasę, zalety w testowaniu i refaktoryzacji kodu, nie wspominając, że jeśli w pewnym momencie zmienisz zdanie na temat potrzeby tylko jednej instancji obiektu, O wiele łatwiej jest usunąć kod, aby zapobiec powielaniu instancji, niż refaktoryzować cały kod zmiennej statycznej, aby użyć zmiennych instancji. Musiałem to zrobić wcześniej, to nie jest fajne, a ty w końcu musisz edytować o wiele więcej klas, co zwiększa ryzyko wprowadzenia nowych błędów ... o wiele lepiej, aby ustawić rzeczy „dobrze” za pierwszym razem, nawet jeśli wydaje się, że ma swoje wady. Dla mnie, wymagana ponowna praca, 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. Dlatego też nie zgadzam 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órych można uzyskać bezpośredni dostęp, zamiast obiektu, który „wie, jak to zrobić coś „na sobie.


11
Podoba mi się twoja odpowiedź, myślę, że skupia się ona na właściwych kompromisach do rozważenia wokół statyki, a nie na niektórych czerwonych śledziach, takich jak współbieżność i zakres. I +1 dla singletonów, lepszym pytaniem może być, kiedy należy używać zmiennych statycznych / metod vs singletonów ...
studgeek

2
Chociaż sam singleton może być bezpieczny dla wątków (np. Przy użyciu synchronizedmetod), nie oznacza to, że kod wywołujący jest wolny od warunków wyścigu w odniesieniu do stanu singletonu.
André Caron,

8
Ponadto statyka nie jest sprzeczna z paradygmatem OOP. Wielu fanatyków OOP powie ci, że klasa jest obiektem, a metoda statyczna jest metodą obiektu klasy, a nie jej instancjami. Zjawisko to jest mniej obecne w Javie. Inne języki, takie jak Python, pozwalają na używanie klas jako zmiennych oraz na dostęp do metod statycznych jako metod tego obiektu.
André Caron

4
Ostatni wiersz trzeciego akapitu powinien zawierać wszystkie zmienne niestatyczne , jeśli się nie mylę.
Steve

1
Object Lifetime, jest jednym z bardzo ważnych punktów wspomnianych przez @jessica.
Abhidemon

93

Zło jest pojęciem subiektywnym.

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

Ponieważ statyka żyje w jednym miejscu, wszystkie wątki, które chcą ich użyć, muszą przejść kontrolę dostępu, którą musisz zarządzać. Oznacza to, że programy są bardziej powiązane i ta zmiana jest trudniejsza do przewidzenia i zarządzania (jak mówi J Skeet). Prowadzi to do problemów z izolowaniem wpływu zmiany, a tym samym wpływa na sposób zarządzania testowaniem.

Są to dwa główne problemy, które mam z nimi.


59

Nie. Globalne stany same w sobie nie są złe. Ale musimy cię zobaczyć kod, aby sprawdzić, czy użyłeś go poprawnie. Jest całkiem możliwe, że nowicjusz narusza państwa globalne; tak jak nadużywałby każdej funkcji języka.

Państwa globalne są absolutną koniecznością. Nie możemy uniknąć państw globalnych. Nie możemy uniknąć rozumowania na temat stanów globalnych. - Jeśli zależy nam na zrozumieniu naszej semantyki aplikacji.

Ludzie, którzy ze względu na to próbują pozbyć się stanów globalnych, nieuchronnie kończą się o wiele bardziej złożonym systemem - a państwa globalne wciąż tam są, sprytnie / idiotycznie zamaskowane pod wieloma warstwami pośrednich; i nadal musimy rozumować o stanach globalnych, po rozpakowaniu wszystkich pośrednich.

Podobnie jak ludzie z Wiosny, którzy hojnie deklarują stany globalne w formacie xml i myślą, że to jakoś lepsze.

@Jon Skeet if I create a new instance of an objectteraz masz dwie rzeczy do przemyślenia - stan w obiekcie i stan środowiska, w którym znajduje się obiekt.


10
„Mam dwie rzeczy do przemyślenia”. Nie, jeśli uzależnię mój test tylko od stanu obiektu. Co jest łatwiejsze, im mniej mam globalny stan.
DJClayworth,

2
Wstrzykiwanie zależności nie ma nic wspólnego ze stanem globalnym ani globalną widocznością - nawet sam kontener nie jest globalny. W porównaniu do „normalnego” kodu jedyną dodatkową rzeczą, dla której widoczny jest obiekt zarządzany przez kontener, jest sam kontener. W rzeczywistości DI jest bardzo często stosowane w celu uniknięcia Wzorca Singletona.
Floegipoky

31

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

  • Bezpieczeństwo wątków - zasoby statyczne z definicji nie są bezpieczne dla wątków
  • Kod Implicity - Nie wiesz, kiedy jest generowana instancja zmiennych statycznych i czy zostanie utworzona instancja przed inną zmienną statyczną

Myślę, że Jon Skeet odniósł się do tego samego komentarza, który opublikowałeś.
RG-3

13
Nie dostaję punktu Bezpieczeństwo wątków, myślę, że nic nie jest bezpieczne dla wątków, chyba że to zrobisz. To nie wydaje się być w ogóle związane ze statycznymi rzeczami, proszę mnie poprawić, jeśli czegoś brakuje.
Zmaster

1
@Zmaster - Chociaż prawdą jest, że bezpieczeństwo wątków nie jest kwestią wyłączną dla zmiennych statycznych, ponieważ z definicji mają być wywoływane z różnych kontekstów, są dla nich bardziej przycinane
sernr

2
@sternr Rozumiem, co masz na myśli, zdarzenie, jeśli „różne konteksty” niekoniecznie muszą być równe „innym wątkom”. Ale prawdą jest, że bezpieczeństwo wątków należy często brać pod uwagę przy zasobach statycznych. Powinieneś rozważyć wyjaśnienie zdania.
Zmaster

Istnieją na przykład prawidłowe wątkowe zastosowania zasobów statycznych. prywatny statyczny końcowy Logger LOG = Logger.getLogger (Foo.class); prywatny statyczny końcowy AtomicInteger x = nowy AtomicInteger (0); Jak rozumiem, statyczne przypisania takich zasobów są gwarantowane przez moduł ładujący w wątkach. Instancja Logger jest lub nie jest wątkowo bezpieczna niezależnie od tego, gdzie przypisujesz do niej wskaźnik. Utrzymywanie stanu w statystyce prawdopodobnie nie jest dobrym pomysłem, ale nie ma powodu, dla którego nie powinien być bezpieczny dla wątków.
teknopaul

29

Jeśli używasz słowa kluczowego „statycznego” bez słowa kluczowego „końcowego”, powinien to być sygnał do dokładnego przemyślenia projektu. Nawet obecność „finału” nie jest wolnym przejściem, ponieważ zmienny statyczny obiekt końcowy może być równie niebezpieczny.

Oceniłbym, że w około 85% przypadków widzę „statyczny” bez „końcowego”, to jest NIEPRAWIDŁOWE. Często znajduję dziwne obejścia, aby ukryć lub ukryć te problemy.

Nie twórz statycznych zmiennych. Zwłaszcza kolekcje. Ogólnie rzecz biorąc, kolekcje powinny być inicjowane, gdy ich obiekt zawierający jest inicjowany i powinny być zaprojektowane w taki sposób, aby były resetowane lub zapominane, gdy ich obiekt zawierający zostanie zapomniany.

Używanie statyki może tworzyć bardzo subtelne błędy, które powodują ból inżynierów przez wiele dni. Wiem, ponieważ zarówno stworzyłem, jak i polowałem na te błędy.

Jeśli chcesz uzyskać więcej informacji, przeczytaj…

Dlaczego nie użyć statyki?

Istnieje wiele problemów ze statyką, w tym pisanie i wykonywanie testów, a także subtelne błędy, które nie są od razu oczywiste.

Kod oparty na obiektach statycznych nie może być łatwo przetestowany jednostkowo, a statyki nie można łatwo wyśmiewać (zwykle).

Jeśli używasz statyki, nie można zamienić implementacji klasy w celu przetestowania komponentów wyższego poziomu. Na przykład wyobraź sobie statycznego CustomerDAO, który zwraca obiekty klienta, które ładuje z bazy danych. Teraz mam klasę CustomerFilter, która musi uzyskać dostęp do niektórych obiektów klienta. Jeśli CustomerDAO jest statyczny, nie mogę napisać testu dla CustomerFilter bez uprzedniej inicjalizacji mojej bazy danych i wypełnienia użytecznych informacji.

A zapełnianie i inicjowanie baz danych zajmuje dużo czasu. Z mojego doświadczenia wynika, że ​​twoja struktura inicjowania bazy danych zmienia się z czasem, co oznacza, że ​​dane zmieniają się, a testy mogą ulec uszkodzeniu. IE, wyobraź sobie, że klient 1 był VIP-em, ale zmieniła się struktura inicjalizacji bazy danych, a teraz klient 1 nie jest już VIP-em, ale twój test został na stałe zakodowany, aby załadować klienta 1…

Lepszym rozwiązaniem jest utworzenie wystąpienia CustomerDAO i przekazanie go do CustomerFilter po jego zbudowaniu. (Jeszcze lepszym rozwiązaniem byłoby użycie Spring lub innej struktury Inversion of Control.

Gdy to zrobisz, możesz szybko wyśmiewać lub wyeliminować alternatywnego DAO w teście CustomerFilterTest, dzięki czemu masz większą kontrolę nad testem,

Bez statycznego DAO test będzie szybszy (bez inicjalizacji db) i bardziej niezawodny (ponieważ nie zawiedzie, gdy zmieni się kod inicjujący db). Na przykład w tym przypadku upewnienie się, że Klient 1 jest i zawsze będzie VIP-em, 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óre pozostają otwarte między testami. Pierwszy test może otworzyć gniazdo na porcie 8080, ale zapomniałeś wyczyścić mapę, gdy test zostanie zerwany. Teraz, gdy uruchamia się drugi test, prawdopodobnie zawiesza się, gdy próbuje utworzyć nowe Socket 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 odśmiecania, co powoduje wyciek pamięci.

Jest to przykład uogólniony, ale w dużych systemach problem ten zdarza się CAŁOŚĆ. Ludzie nie myślą o testach jednostkowych kilkakrotnie uruchamiających i zatrzymujących swoje oprogramowanie w tej samej maszynie JVM, ale jest to dobry test projektu oprogramowania, a jeśli masz aspiracje do wysokiej dostępności, musisz o tym wiedzieć.

Problemy te często pojawiają się w przypadku obiektów struktury, na przykład dostępu do bazy danych, buforowania, przesyłania wiadomości i rejestrowania. Jeśli korzystasz z Java EE lub najlepszych frameworków, prawdopodobnie wiele z nich zarządza, ale jeśli podobnie jak ja masz do czynienia ze starszym systemem, możesz mieć wiele niestandardowych ram dostępu do tych warstw.

Jeśli konfiguracja systemu mająca zastosowanie do tych komponentów struktury zmienia się między testami jednostkowymi, a struktura testów jednostkowych nie rozrywa i nie odbudowuje komponentów, zmiany te nie mogą zostać zastosowane, a gdy test opiera się na tych zmianach, nie powiodą się .

Problem ten dotyczą nawet komponentów innych niż frameworki. Wyobraź sobie statyczną mapę o nazwie OpenOrders. Piszesz jeden test, który tworzy kilka otwartych zamówień, i sprawdza, 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 w mapie OpenOrders, a następnie potwierdza, że ​​liczba zamówień jest dokładna. Uruchamiane indywidualnie, oba testy przeszłyby pomyślnie, ale jeśli zostaną uruchomione razem w pakiecie, nie powiedzie się.

Co gorsza, niepowodzenie może zależeć od kolejności, w której testy zostały uruchomione.

W takim przypadku, unikając statyki, unikasz ryzyka utrwalenia danych w różnych instancjach testowych, zapewniając lepszą niezawodność testu.

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, ten sam problem, o którym mowa powyżej w przypadku zestawów testów jednostkowych, może mieć zastosowanie, gdy kod działa również w środowisku produkcyjnym.

W przypadku wątków zamiast używać obiektu statycznego do przechowywania danych, lepiej jest użyć obiektu zainicjowanego podczas fazy uruchamiania wątku. W ten sposób za każdym razem, gdy wątek jest uruchamiany, tworzona jest nowa instancja obiektu (z potencjalnie nową konfiguracją), dzięki czemu unikasz danych z jednej instancji wątku krwawiącej do następnej.

Kiedy wątek umiera, obiekt statyczny nie jest resetowany lub śmieci są gromadzone. Wyobraź sobie, że masz wątek o nazwie „EmailCustomers”, a gdy się uruchomi, zapełni statyczną kolekcję Ciągów listą adresów e-mail, a następnie rozpocznie wysyłanie wiadomości e-mail 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 ponownie uruchamia wątek. Następnie, gdy wątek się uruchamia, przeładowuje listę klientów. Ponieważ jednak kolekcja jest statyczna, może zachować listę adresów e-mail z poprzedniej kolekcji. Teraz niektórzy klienci mogą otrzymywać zduplikowane wiadomości e-mail.

Na bok: finał statyczny

Użycie „static static” jest faktycznie odpowiednikiem języka Java dla C #define, chociaż istnieją techniczne różnice w implementacji. AC / C ++ #define jest zamieniany z kodu przez preprocesor przed kompilacją. „Statyczny finał” Java zakończy się rezydencją pamięci na stosie. W ten sposób jest bardziej podobny 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 korzystasz z nowoczesnego frameworka Java, takiego jak Java EE lub Spring itp., Możesz nie spotkać wielu z tych sytuacji, ale jeśli pracujesz z dużą ilością starszego kodu, mogą one stać się znacznie częstsze.


15

Ponieważ nikt nie wspomniał o tym: współbieżność. Zmienne statyczne mogą cię zaskoczyć, jeśli masz wiele wątków odczytujących i zapisujących zmienną statyczną. Jest to powszechne w aplikacjach internetowych (np. ASP.NET) i może powodować pewne irytujące 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 w tym samym czasie”, jeden użytkownik może uzyskać wynik oczekiwany przez drugiego użytkownika lub gorzej.

statyka redukuje wzajemne zależności od innych części kodu. Mogą działać jako posiadacze doskonałego stanu

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

* Właściwie o tym wspomniał Preet Sangha .


5
Zmienne instancji nie mają przewagi bezpieczeństwa wątków nad statyką, wszystkie są zmiennymi niechronionymi. Zamiast tego wszystko sprowadza się do ochrony kodu, który uzyskuje dostęp do tych zmiennych.
studgeek

2
Nie do końca tak twierdziłem, ale ze względu na dyskusję: separacja jest formą ochrony. Stany wątków są rozdzielone; stan globalny nie jest . Zmienna instancji nie potrzebuje ochrony, chyba że jest jawnie współdzielona między wątkami; zmienna statyczna jest zawsze wspólna dla wszystkich wątków w tym procesie.
Justin M. Keyes,

Chciałbym, aby zmienne statyczne wątkowe były bardziej idealną koncepcją, ponieważ mogą być bardzo przydatne do bezpiecznego udostępniania informacji zawiniętemu wywołaniu podprogramu bez konieczności przepuszczania tych informacji przez każdą warstwę opakowania. Na przykład, jeśli obiekt ma metody renderowania go do bieżącego kontekstu graficznego wątku, a istnieją metody zapisywania / przywracania bieżącego kontekstu graficznego, użycie tych może być często czystsze niż konieczność przekazywania kontekstu graficznego przez każde wywołanie metody.
supercat

15

Podsumowując kilka podstawowych zalet i wad stosowania metod statycznych w Javie:

Zalety:

  1. Globalnie dostępny, tzn. Niepowiązany z żadną konkretną instancją obiektu.
  2. Jedna instancja na JVM.
  3. Można uzyskać dostęp za pomocą nazwy klasy (nie wymaga obiektu).
  4. Zawiera jedną wartość mającą zastosowanie do wszystkich instancji.
  5. Obciążenie przy uruchamianiu JVM i umiera, gdy JVM zostanie zamknięty.
  6. Nie modyfikują stanu obiektu.

Niedogodności:

  1. Członkowie statyczni są zawsze częścią pamięci, niezależnie od tego, czy są w użyciu, czy nie.
  2. Nie można kontrolować tworzenia i niszczenia zmiennej statycznej. Przydatnie zostały one utworzone przy ładowaniu programu i zniszczone po rozładowaniu programu (lub po wyłączeniu JVM).
  3. Możesz zapewnić bezpieczeństwo wątków statycznych za pomocą synchronizacji, ale potrzebujesz dodatkowych wysiłków.
  4. Jeśli jeden wątek zmieni wartość zmiennej statycznej, która może zepsuć funkcjonalność innych wątków.
  5. Musisz wiedzieć „statyczny” przed użyciem.
  6. Nie można przesłonić metod statycznych.
  7. Serializacja nie działa z nimi dobrze.
  8. Nie uczestniczą w polimorfizmie środowiska uruchomieniowego.
  9. Jeśli używana jest duża liczba zmiennych statycznych / metod, występuje problem z pamięcią (do pewnego stopnia, ale chyba niewiele). Ponieważ nie będą one usuwane do momentu zakończenia programu.
  10. Metody statyczne są również trudne do przetestowania.

Wady 6, 7, 8 i 10 to wady używanych języków / ram, a nie wady zmiennych statycznych w ogóle. Wady 1, 4 i 5 istnieją również w przypadku innych rozwiązań, takich jak niektóre wzorce singletonów zapewniane przez niektóre ramy. (Nie głosowałem na odpowiedź, ponieważ zgadzam się z resztą i jest to ładna kolekcja.)
Peter - Przywróć Monikę

13

gdybym musiał wykonać 10 000 wywołań funkcji w klasie, chętnie uczynię metodę statyczną i użyję na niej prostej class.methodCall () zamiast zaśmiecać pamięć 10 000 wystąpień klasy, prawda?

Musisz zrównoważyć potrzebę enkapsulacji danych do obiektu ze stanem, a potrzebę po prostu obliczenia wyniku funkcji na niektórych danych.

Ponadto statyka zmniejsza wzajemne zależności od innych części kodu.

Podobnie jak kapsułkowanie. W dużych zastosowaniach statyka zwykle wytwarza kod spaghetti i nie pozwala łatwo refaktoryzować lub testować.

Inne odpowiedzi dostarczają również uzasadnionych powodów do nadmiernego używania statyki.


13

Zmienne statyczne są ogólnie uważane za złe, ponieważ reprezentują stan globalny i dlatego są znacznie trudniejsze do uzasadnienia. W szczególności łamią założenia programowania obiektowego. W programowaniu obiektowym każdy obiekt ma swój własny stan, reprezentowany przez zmienne instancji (niestatyczne). Zmienne statyczne reprezentują stan w instancjach, które mogą być znacznie trudniejsze do przetestowania jednostkowego. Wynika to głównie z tego, że trudniej jest oddzielić zmiany zmiennych statycznych do pojedynczego testu.

Biorąc to pod uwagę, ważne jest, aby wprowadzić rozróżnienie między zwykłymi zmiennymi statycznymi (ogólnie uważanymi za złe) a końcowymi zmiennymi statycznymi (stałe AKA; nie tak źle).


4
„Zmienne statyczne reprezentują stan w różnych klasach” ... Myślę, że masz na myśli „zmienne statyczne reprezentują stan w różnych instancjach”? +1 za „ostateczne statyczne stałe AKA, nie takie złe”. Ponieważ wartość nie może się zmienić, wszystko, co od niej zależy w danym momencie, nie może pośrednio zmienić swojego zachowania w późniejszym czasie - wartość jest taka sama.
Jared Updike,

„Zmienne statyczne reprezentują stan w różnych instancjach” to znacznie lepszy sposób na określenie tego. Zredagowałem swoją odpowiedź.
Jack Edmonds,

9

Moim zdaniem prawie nigdy nie chodzi o wydajność, chodzi o design. Nie uważam używania metod statycznych za niewłaściwe, jak na przykład stosowanie zmiennych statycznych (ale myślę, że tak naprawdę mówisz o wywołaniach metod).

Chodzi po prostu o to, jak odizolować logikę i dać jej dobre miejsce. Czasami uzasadnia to stosowanie metod statycznych, których java.lang.Mathjest dobrym przykładem. Myślę, że kiedy wymieniasz większość swoich klas XxxUtillub Xxxhelperlepiej przemyśleć swój projekt.


3
Metody statyczne bez skutków ubocznych są całkowicie w porządku IMO. Ale globalny stan zmienny rzadko jest i interpretuję OP jako mówienie o stanie globalnym.
CodesInChaos

1
@CodeInChaos całkowicie się zgadza. Uważam, że OP nie jest całkowicie jasne na temat różnicy między metodami statycznymi a zmiennymi.
M Platvoet,

8

Właśnie streściłem niektóre punkty przedstawione w odpowiedziach. Jeśli znajdziesz coś złego, możesz to poprawić.

Skalowanie: Mamy dokładnie jedną instancję zmiennej statycznej na JVM. Załóżmy, że opracowujemy system zarządzania biblioteką i postanowiliśmy nadać nazwie książki zmienną statyczną, ponieważ jest tylko jedna na książkę. Ale jeśli system rośnie i używamy wielu maszyn JVM, to nie mamy sposobu, aby dowiedzieć się, z którą książką mamy do czynienia?

Bezpieczeństwo wątków: Zarówno zmienna instancji, jak i zmienna statyczna muszą być kontrolowane, gdy są używane w środowisku wielowątkowym. Ale w przypadku zmiennej instancji nie potrzebuje ochrony, chyba że jest jawnie współużytkowana przez wątki, ale w przypadku zmiennej statycznej jest zawsze współużytkowana przez wszystkie wątki w procesie.

Testowanie: Chociaż projekt do przetestowania nie jest równoznaczny z dobrym projektem, ale rzadko obserwujemy dobry projekt, którego nie można przetestować. Ponieważ zmienne statyczne reprezentują stan globalny i bardzo trudno jest je przetestować.

Rozumowanie na temat stanu: jeśli utworzę nową instancję klasy, możemy uzasadnić stan tej instancji, ale jeśli ma ona zmienne statyczne, 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 z nimi dobrze.

Stworzenie i zniszczenie: Tworzenie i niszczenie zmiennych statycznych nie może być kontrolowane. Zazwyczaj są one tworzone i niszczone podczas ładowania i rozładowywania programu. Oznacza to, że źle wpływają na zarządzanie pamięcią, a także sumują czas inicjalizacji podczas uruchamiania.

Ale co jeśli naprawdę ich potrzebujemy?

Ale czasami możemy ich naprawdę potrzebować. Jeśli naprawdę odczuwamy potrzebę wielu zmiennych statycznych, które są wspólne dla aplikacji, jedną z opcji jest użycie wzorca Singleton Design, który będzie zawierał wszystkie te zmienne. Lub możemy stworzyć jakiś obiekt, który będzie miał zmienną statyczną i może być przekazywany.

Również jeśli zmienna statyczna jest oznaczona jako końcowa, staje się stałą, a przypisanej jej wartości raz nie można zmienić. Oznacza to, że uratuje nas od wszystkich problemów, które napotykamy ze względu na jego zmienność.


7

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

Zmienne statyczne nie są złe - mają swoje zastosowanie jako zmienne globalne, takie jak stałe w większości przypadków w połączeniu z ostatecznym modyfikatorem, ale jak już powiedziano, nie nadużywaj ich.

Metody statyczne zwane także metodami użyteczności. Zasadniczo korzystanie z nich nie jest złą praktyką, ale głównym problemem jest to, że mogą one utrudniać testowanie.

Jako przykład świetnego projektu Java, który wykorzystuje dużo statyki i robi to we właściwy sposób, spójrz na Play! ramy . W SO jest również dyskusja na ten temat.

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

Tak więc zmienne statyczne (i metody) są dobre, ale używaj ich mądrze!


6

Najważniejsze są zmienne statyczne, które powodują problemy z bezpieczeństwem danych (każda zmiana może być zmieniona, każdy może zmienić, bezpośredni dostęp bez obiektu itp.)

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


6

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

Problem ze stanami globalnymi polega na tym, że czasami to, co ma sens jako globalne w prostszym kontekście, musi być nieco bardziej elastyczne w praktycznym kontekście, i tam właśnie przydatny jest wzór singletonu.


5

Kolejny powód: kruchość.

Jeśli masz klasę, większość ludzi spodziewa się, że będzie w stanie ją utworzyć i korzystać z niej do woli.

Możesz udokumentować, że tak nie jest, lub zabezpieczyć się przed tym (wzór singleton / fabryka) - ale to dodatkowa praca, a zatem dodatkowa opłata. Nawet wtedy, w dużej firmie, istnieje szansa, że ​​ktoś w pewnym momencie spróbuje skorzystać z twojej klasy, nie zwracając uwagi na wszystkie miłe komentarze lub fabrykę.

Jeśli często używasz zmiennych statycznych, to się zepsuje. Błędy są drogie.

Pomiędzy poprawą wydajności o 0,0001% a odpornością na zmiany przez potencjalnie nieświadomych programistów, w wielu przypadkach solidność jest dobrym wyborem.


4

Uważam, że zmienne statyczne są wygodniejsze w użyciu. Zakładam też, że są one również wydajne (proszę o poprawienie, jeśli się mylę), ponieważ gdybym musiał wykonać 10.000 wywołań funkcji w klasie, chętnie uczynię metodę statyczną i użyję prostej class.methodCall () na nim zamiast zaśmiecać pamięć 10.000 wystąpień klasy, prawda?

Rozumiem, co myślisz, ale prosty wzorzec Singleton zrobi to samo bez konieczności tworzenia 10 000 obiektów.

metod statycznych można używać, ale tylko w przypadku funkcji powiązanych z domeną obiektu i nie wymagających wewnętrznych właściwości obiektu ani ich nie używających.

dawny:

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

    public static int convertToGallon(int liters)...

    public static int convertToLiters(int gallon)...

}

Klasyczny singleton (tj. Ten, do którego można uzyskać dostęp Class.Instance) jest niewiele lepszy niż zmienna statyczna. Jest to nieco bardziej testowalne, ale wciąż znacznie gorsze niż projekty, w których akurat tworzysz jedną instancję zamiast budować kod przy założeniu, że jest tylko jedna.
CodesInChaos

Nie jestem pewien, czy rozumiem twój komentarz! odpowiadałem OP na to, co napisał kursywą na temat wystąpienia 10 000 obiektów. Nie rozumiem, dlaczego porównujesz singleton i zmienną statyczną? Rozumiem z tego, co napisałeś, że Singleton to zły projekt ...! Chyba cię źle zrozumiałem, ponieważ Spring Framework domyślnie tworzy wszystkie fasole Singleton ;-)
Cygnusx1

Klasycznym singletonem (który ma Class.Instance), który ma stan zmienny, jest zły projekt IMO. W takim przypadku zdecydowanie wolę projekt, w którym otrzymuję singletony, których muszę użyć, przekazane jako parametr do klasy, która ich używa (zazwyczaj za pomocą DI). Logicznie niezmienne klasyczne singletony są w porządku IMO.
CodesInChaos

@ Cygnusx1 W przypadku, gdy nie było jasne, dlaczego singleton klasy (singleton, w którym klasa zapewnia pojedynczy egzemplarz) nie jest łatwo testowalny, ściśle wiąże istnienie klasy z cyklem życia programu. Aby go przetestować, musisz przestrzegać zasad uruchamiania i zamykania programu, co często ma skutki uboczne nieistotne dla testowania klasy. Jeśli działało to skutecznie jako singleton (jedna kopia w programie, ale w innym przypadku nie było egzekwowania), można utworzyć wiele kopii w czasie testu bez programu, sprawdzając, czy zachowanie w całej klasie jest takie, jakie powinno być dla każdego scenariusza testowania.
Edwin Buck

4

Kwestia „Statyka jest zła” jest bardziej kwestią dotyczącą państwa globalnego. Odpowiedni czas, aby zmienna była statyczna, to jeśli nie ma ona nigdy więcej niż jednego stanu; Narzędzia IE, które powinny być dostępne dla całego frameworka 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 zmienne statyczne są wygodniejsze w użyciu. I zakładam, że są również wydajne

Statyka jest idealnym i wydajnym wyborem dla zmiennych / klas, które nigdy się nie zmieniają .

Problemem ze stanem globalnym jest nieodłączna niekonsekwencja, którą może on tworzyć. Dokumentacja na temat testów jednostkowych często rozwiązuje ten problem, ponieważ za każdym razem, gdy istnieje stan globalny, do którego może uzyskać dostęp więcej niż wiele niepowiązanych obiektów, testy jednostkowe będą niepełne, a nie „jednostkowe”. Jak wspomniano w tym artykule o stanie globalnym i singletonach , jeśli obiekty A i B nie są ze sobą powiązane (ponieważ w jednym nie podano wyraźnego odniesienia do innego), A nie powinno mieć wpływu na stan B.

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


„Czas ma charakter globalny” - istnieją inne sposoby modelowania czasu w systemach obliczeniowych, niż posiadanie jakiejś domyślnej, globalnej rzeczy, która zmienia się sama. por. ankieta: „Modelowanie czasu w informatyce: taksonomia i ankieta porównawcza” @ arxiv.org/abs/0807.4132
Jared Updike

4

Moje 0,02 $ jest takie, że kilka z tych odpowiedzi myli problem, zamiast mówić „statyka jest zła”. Myślę, że lepiej jest mówić o określaniu zakresu i instancjach.

Powiedziałbym, że statyczny jest zmienną „klasową” - reprezentuje wartość wspólną dla wszystkich instancji tej klasy. Zazwyczaj należy go również tak objąć (chroniony lub prywatny dla klasy i jej instancji).

Jeśli planujesz łączyć zachowanie na poziomie klasy i wystawiać go na działanie innego kodu, to singleton może być lepszym rozwiązaniem do obsługi zmian w przyszłości (jak sugeruje @Jessica). Jest tak, ponieważ można używać interfejsów na poziomie instancji / singletonu w sposób, którego nie można używać na poziomie klasy - w szczególności dziedziczenia.

Niektóre przemyślenia na temat tego, dlaczego uważam, że niektóre aspekty innych odpowiedzi nie są kluczowe dla pytania ...

Statyka nie jest „globalna”. W Javie zakres jest kontrolowany niezależnie od statycznego / wystąpienia.

Współbieżność jest nie mniej niebezpieczna dla statyki niż metody instancji. To wciąż stan, który należy chronić. Jasne, że możesz mieć 1000 instancji ze zmienną instancji i tylko jedną zmienną statyczną, ale jeśli dostęp do któregokolwiek z nich nie jest zapisany w sposób bezpieczny dla wątków, nadal jesteś wkręcony - może to trochę potrwać, zanim zdasz sobie z tego sprawę .

Zarządzanie cyklem życia jest interesującym argumentem, ale myślę, że jest mniej ważny. Nie rozumiem, dlaczego trudniej jest zarządzać parą metod klasowych, takich jak init () / clear (), niż tworzenie i niszczenie instancji singleton. W rzeczywistości niektórzy mogą powiedzieć, że singleton jest nieco bardziej skomplikowany z powodu GC.

PS W zakresie Smalltalk wiele jego dialektów ma zmienne klasowe, ale w klasach Smalltalk są tak naprawdę instancje Metaclass, więc tak naprawdę są to zmienne w instancji Metaclass. Mimo to zastosowałbym tę samą zasadę. Jeśli są one używane do współdzielenia stanu między instancjami, to dobrze. Jeśli obsługują funkcje publiczne, powinieneś spojrzeć na Singleton. Westchnienie, na pewno tęsknię za Smalltalk ...


4

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

Po pierwsze, o zmiennych statycznych. Zmienne statyczne są całkowicie niepotrzebne, a jego użycia można łatwo uniknąć. Ogólnie w języku OOP, aw szczególności w Javie, parametry funkcji są zestawiane przez odwołanie, to znaczy, jeśli przekazujesz obiekt do funcionta, 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 sugeruje to, że zapełnisz pamięć wskaźnikami, nie będzie to koniecznie oznaczać słabej wydajności, ponieważ rzeczywiste systemy dostrajania pamięci są zoptymalizowane do obsługi tego i utrzymają w pamięci strony, do których odnoszą się wskaźniki przekazane do nowego zakres; użycie zmiennych statycznych może spowodować, że system załaduje stronę pamięci, w której są przechowywane, gdy trzeba uzyskać do nich dostęp (stanie się to, jeśli strona nie zostanie otwarta przez długi czas). Dobrą praktyką jest łączenie wszystkich tych statycznych elementów w małe „klauzule konfiguracyjne”, zapewni to, że system umieści to wszystko na tej samej stronie pamięci.

Po drugie, o metodach statycznych. Metody statyczne nie są takie złe, ale mogą szybko zmniejszyć wydajność. Pomyślmy na przykład o metodzie, która porównuje dwa obiekty klasy i zwraca wartość wskazującą, który z obiektów jest większy (typowa metoda porównania), ta metoda może być statyczna lub nie, ale przy jej wywołaniu forma niestatyczna będzie bardziej skuteczna ponieważ będzie musiał rozwiązać tylko dwa odwołania (jeden dla każdego obiektu) skierowane do trzech odwołań, które będą musiały rozwiązać statyczną wersję tej samej metody (jeden dla klasy plus dwa, jeden dla każdego obiektu). Ale jak mówię, nie jest tak źle, jeśli spojrzymy na klasę 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,

Podsumowując: Unikaj stosowania zmiennych statycznych i znajdź prawidłową równowagę wydajności w przypadku metod statycznych lub niestatycznych.

PS: Przepraszam za mój angielski.


4

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


3

a) Powód dotyczący programów.

Jeśli masz program dla małych i średnich rozmiarów, do którego można uzyskać dostęp do zmiennej statycznej Global.foo, wywołanie do niej zwykle przychodzi znikąd - nie ma ścieżki, a zatem nie ma osi czasu, w jaki sposób zmienna dociera do miejsca, w którym się znajduje jest używany. Skąd mam wiedzieć, kto ustawił wartość rzeczywistą? Skąd mam wiedzieć, co się stanie, jeśli zmienię go teraz? Mam grep nad całym źródłem, aby zebrać wszystkie dostępy, wiedzieć, co się dzieje.

Jeśli wiesz, jak go używać, 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 zapobiegają uruchamianiu wielu programów tego samego rodzaju w tej samej maszynie JVM z różnymi wartościami. Często nie przewiduje się zastosowań, w których więcej niż jedna instancja programu jest przydatna, ale jeśli ewoluuje lub jest przydatna dla innych, mogą wystąpić sytuacje, w których chcieliby uruchomić więcej niż jedną instancję programu .

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


3

wszystko (może :) mieć 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 jednej JVM) statyczny jest najlepszym wyborem

-> oczywiście możesz wymusić tylko jeden przykład, ale dlaczego?
niektóre komentarze w tym wątku uważam za złe, a nie statykę;)


3

Zmienne statyczne nie są dobre ani złe. Reprezentują atrybuty opisujące całą klasę, a nie konkretną instancję. Jeśli potrzebujesz licznika dla wszystkich instancji określonej klasy, zmienna statyczna byłaby właściwym miejscem do przechowywania wartości.

Problemy pojawiają się, gdy próbujesz użyć zmiennych statycznych do przechowywania wartości powiązanych z instancją.


2

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 obiektowy, podczas gdy w rzeczywistości tak nie jest. To po prostu zło.


1
Ale czy sztywne uznanie twojego kodu za zgodny z jakimkolwiek arbitralnym standardowym paradygmatem faktycznie poprawia kod, czy też narzekamy, aby unikać pisania kodu, który działa?
Zoey,

Tak, robi to lepiej, ponieważ ułatwia zarządzanie w przyszłości, jest łatwiejszy do zrozumienia i wyraźniejszy.
blockhead

1
Dlaczego źle jest nie pisać kodu OO? i dlaczego Bjarne Stroustrup się z tobą nie zgadza? wymienić tylko jeden ...
Markiz Lorne

2
Nie powiedziałem, że to zło nie pisać kodu OO. Powiedziałem, że to zło myśleć, że piszesz kod OO, kiedy wszystko, czym jesteś, ukrywa globale za statycznymi metodami i właściwościami. Przeczytaj ponownie to, co napisałem.
blockhead

2

Jest tutaj wiele dobrych odpowiedzi, dodając do tego,

Pamięć: Zmienne statyczne są aktywne tak długo, jak długo trwa moduł ładujący klasy [ogólnie do śmierci VM], ale dotyczy to tylko obiektów / odniesień masowych przechowywanych jako statyczne.

Modularyzacja: rozważ pojęcia takie jak IOC, dependenceInjection, proxy itp. Wszystkie są całkowicie przeciwne ścisłym sprzężeniom / implementacjom statycznym.

Inne wady: bezpieczeństwo wątku, testowalność


0

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


0

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


0

Z mojego punktu widzenia staticzmienną powinny być tylko dane do odczytu lub zmienne tworzone zgodnie z konwencją .

Na przykład mamy interfejs jakiegoś projektu i mamy listę krajów, języków, ról użytkowników itp. I mamy klasę do uporządkowania tych danych. mamy absolutną pewność, że aplikacja nie będzie działać bez tych list. więc pierwszą czynnością, którą wykonujemy przy inicjowaniu aplikacji, jest sprawdzenie tej listy w poszukiwaniu aktualizacji i pobranie tej listy z interfejsu API (w razie potrzeby). Zgadzamy się więc, że te dane są „zawsze” obecne w aplikacji. Są to praktycznie tylko dane do odczytu, więc nie musimy dbać o jego stan - myśląc o tym przypadku, naprawdę nie chcemy mieć wielu wystąpień tych danych - ta sprawa wygląda na idealnego kandydata do bycia statycznym .


0

Dużo grałem ze statyką i czy mogę dać ci nieco inną odpowiedź - a może nieco inny sposób patrzenia na to?

Kiedy użyłem statyki na zajęciach (członkowie i obie metody), w końcu zacząłem zauważać, że moja klasa to tak naprawdę dwie klasy dzielące odpowiedzialność - jest część „statyczna”, która działa bardzo podobnie do singletona, a nie ma -statyczna część (normalna klasa). O ile wiem, zawsze możesz całkowicie oddzielić te dwie klasy, po prostu wybierając wszystkie statykę dla jednej klasy i niestatyczność dla drugiej.

To się często zdarzało, gdy miałem klasyczną kolekcję wewnątrz klasy, która zawiera instancje klasy i kilka statycznych metod zarządzania kolekcją. Kiedy się nad tym zastanowisz, oczywiste jest, że twoja klasa nie robi „tylko jednej rzeczy”, jest kolekcją i robi coś zupełnie innego.

A teraz poprawmy nieco problem: jeśli podzielisz klasę na jedną klasę, w której wszystko jest statyczne, a drugą, która jest tylko „klasą normalną” i zapomnisz o „klasie normalnej”, twoje pytanie stanie się klasą czysto statyczną vs. Singletonem, który jest skierowana w długości tutaj (i prawdopodobnie kilkanaście innych pytań).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.