Kiedy nie używać słowa kluczowego statycznego w Javie?

Kiedy uważa się za słabą praktykę używanie statycznego słowa kluczowego w Javie na podpisach metod? Jeśli metoda wykonuje funkcję opartą na pewnych argumentach i nie wymaga dostępu do pól, które nie są statyczne, to czy nie zawsze chciałbyś, aby te typy metod były statyczne?

Author: Jonik, 2009-11-20

9 answers

Jednym z powodów, dla których Może nie chcieć, aby była statyczna, jest umożliwienie jej nadpisania w podklasie. Innymi słowy, zachowanie może nie zależeć od danych wewnątrz obiektu, ale od dokładnego typu obiektu. Na przykład możesz mieć ogólny typ kolekcji, z właściwością isReadOnly, która zwróci false w kolekcjach zawsze zmienialnych, true w kolekcjach zawsze niezmiennych i będzie zależna od zmiennych instancji w innych.

Jednak w moim doświadczeniu jest to dość rzadkie - i zazwyczaj powinny być wyraźnie określone dla jasności. Normalnie zrobiłbym statyczną metodę, która nie zależy od stanu obiektu.
 31
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
2009-11-19 21:46:44

Dwa największe zło, jakie kiedykolwiek spotkasz w wielkoskalowych aplikacjach Java to

  • metody statyczne, z wyjÄ…tkiem tych, które sÄ… czystymi funkcjami*
  • zmienne pola statyczne

Niszczą one modułowość, rozszerzalność i testowalność Twojego kodu do tego stopnia, że zdaję sobie sprawę, że nie mogę mieć nadziei, aby przekonać cię do tego w tak ograniczonym czasie i przestrzeni.

* "czysta funkcja" to każda metoda, która nie modyfikuje żadnego stanu i której wynik nie zależy od niczego ale parametry dostarczone do niego. Tak więc, na przykład, każda funkcja, która wykonuje I / O (bezpośrednio lub pośrednio) nie jest czystą funkcją, ale Math.sqrt (), oczywiście.

Więcej blahblah o czystych funkcjach (self-link) i dlaczego chcesz się ich trzymać.

Gorąco zachęcam do promowania stylu programowania" dependency injection", prawdopodobnie wspieranego przez framework taki jak Spring lub Guice (zastrzeżenie: jestem współautorem tego ostatniego). Jeśli zrobisz to dobrze, będziesz zasadniczo nigdy nie potrzebują zmiennego stanu statycznego lub nieczystych metod statycznych.

 42
Author: Kevin Bourrillion,
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
2009-11-19 21:40:52

Ogólnie rzecz biorąc, preferuję metody instancji z następujących powodów:

  1. Statyczne metody utrudniają testowanie, ponieważ nie można ich zastąpić,
  2. metody statyczne sÄ… bardziej zorientowane proceduralnie.

Moim zdaniem metody statyczne są w porządku dla klas użytkowych (jak StringUtils), ale wolę unikać ich jak najwięcej.

 23
Author: Pascal Thivent,
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
2009-11-19 23:00:04

To, co mówisz, jest w pewnym sensie prawdą, ale co się stanie, gdy chcesz nadpisać zachowanie tej metody w klasie pochodnej? Nie możesz tego zrobić.

Jako przykład rozważ następującą klasę typu DAO:

class CustomerDAO {
    public void CreateCustomer( Connection dbConn, Customer c ) {
       // Some implementation, created a prepared statement, inserts the customer record.
    }

    public Customer GetCustomerByID( Connection dbConn, int customerId ) {
       // Implementation
    }
}
Żadna z tych metod nie wymaga żadnego "stanu". Wszystko, czego potrzebują, jest przekazywane jako parametry. Więc łatwo mogą być statyczne. Teraz pojawia się wymóg, że musisz obsługiwać inną bazę danych (powiedzmy Oracle)

Ponieważ te metody nie są statyczne, można po prostu utworzyć nową klasę DAO:

class OracleCustomerDAO : CustomerDAO {
    public void CreateCustomer( Connection dbConn, Customer c ) {
        // Oracle specific implementation here.
    }

    public Customer GetCustomerByID( Connection dbConn, int customerId ) {
        // Oracle specific implementation here.
    }
}

Ta nowa klasa może być teraz używana w miejsce starej. Jeśli używasz iniekcji zależnościowej, może to nawet nie wymagać zmiany kodu.

Ale gdybyśmy uczynili te metody statycznymi, to wszystko byłoby bardziej skomplikowane, ponieważ nie możemy po prostu nadpisać statycznych metod w nowej klasie.

 4
Author: Eric Petroelje,
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
2009-11-19 21:46:23

Metody statyczne są zwykle pisane do dwóch celów. Pierwszym celem jest posiadanie pewnego rodzaju globalnej metody użytkowej, podobnej do funkcjonalności dostępnej w Javie.util.Kolekcje . Te statyczne metody są na ogół nieszkodliwe. Drugim celem jest kontrolowanie tworzenia obiektów i ograniczanie dostępu do zasobów (takich jak połączenia z bazą danych) za pomocą różnych wzorców projektowych, takich jak singletons i factories. Mogą one, jeśli są źle wdrożone, skutkować problemy.

Dla mnie sÄ… dwa minusy stosowania metod statycznych:

  1. sprawiają, że kod jest mniej modułowy i trudniejszy do przetestowania / rozszerzenia. Większość odpowiedzi już się tym zajęła, więc nie będę już się tym przejmować.
  2. metody statyczne mają tendencję do tworzenia jakiejś formy stanu globalnego, co często jest przyczyną podstępnych błędów. Może to nastąpić w źle napisanym kodzie, który jest napisany dla drugiego celu opisanego powyżej. Pozwól mi rozwinąć.

Na przykład, rozważmy projekt, który wymaga rejestrowania pewnych zdarzeń do bazy danych i opiera się na połączeniu z bazą danych dla innego stanu, jak również. Załóżmy, że zwykle najpierw inicjowane jest połączenie z bazą danych, a następnie framework logowania jest skonfigurowany do zapisywania pewnych zdarzeń dziennika do bazy danych. Teraz Załóżmy, że deweloperzy zdecydują się przejść z ręcznie pisanego frameworka bazy danych do istniejącej frameworka bazy danych, takiej jak hibernate.

Jednak ten framework prawdopodobnie będzie miał własne logowanie Konfiguracja-a jeśli zdarza się, że używa tego samego frameworka logowania, co Twój, to istnieje duża szansa, że będą różne konflikty między konfiguracjami. Nagle przejście na inny framework bazy danych powoduje błędy i awarie w różnych częściach systemu, które pozornie nie są ze sobą powiązane. Powodem takich awarii może się zdarzyć, ponieważ konfiguracja logowania zachowuje stan globalny dostęp za pomocą statycznych metod i zmiennych, a różne właściwości konfiguracji mogą być nadpisywane przez różne części systemu.

Aby uniknąć tych problemów, programiści powinni unikać przechowywania dowolnego stanu za pomocą statycznych metod i zmiennych. Zamiast tego powinni tworzyć czyste interfejsy API, które pozwalają użytkownikom zarządzać stanem i izolować go w razie potrzeby. BerkeleyDB jest dobrym przykładem tutaj, enkapsulating state via Environment object zamiast poprzez wywołania statyczne.

 1
Author: toluju,
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
2009-11-19 23:30:30

Zgadza się. W rzeczy samej, musisz przekreślić to, co w przeciwnym razie mogłoby być rozsądnym projektem (aby mieć pewne funkcje nie powiązane z klasą) w terminach Java. Dlatego widzisz wszystkie klasy, takie jak FredsSwingUtils i YetAnotherIOUtils.

 0
Author: Jonathan Feinberg,
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
2009-11-19 21:35:59

Jeśli chcesz użyć członka klasy niezależnie od dowolnego obiektu tej klasy, powinien on być zadeklarowany jako statyczny.
Jeśli jest zadeklarowana jako statyczna, może być dostępna bez istniejącej instancji obiektu klasy. Statyczny element jest współdzielony przez wszystkie obiekty danej klasy.

 0
Author: Gnark,
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
2009-11-19 21:39:11

Dodatkowa irytacja dotycząca metod statycznych: nie ma łatwego sposobu na przekazanie odniesienia do takiej funkcji bez utworzenia wokół niej klasy wrappera. Np.-coś w stylu:

FunctorInterface f = new FunctorInterface() { public int calc( int x) { return MyClass.calc( x); } };

Nienawidzę tego rodzaju Java make-work. Może w późniejszej wersji Javy pojawią się delegaty lub podobny mechanizm typu funkcyjnego / proceduralnego?

Drobny bełkot, ale jeszcze jedno do , a nie do , Jak o darmowych funkcjach statycznych, er, metodach.

 0
Author: Roboprog,
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
2009-11-19 22:06:20

Dwa pytania tutaj 1) statyczna metoda, która tworzy obiekty, pozostaje załadowana w pamięci, gdy jest dostępna po raz pierwszy? Czy nie jest to (pozostając w pamięci) wadą? 2) jedną z zalet korzystania z Javy jest jej funkcja garbage collection - czy nie ignorujemy tego, gdy używamy metod statycznych?

 0
Author: Subramanian,
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
2010-03-09 06:41:04