Let's say I have a class designed to be instantiated. I have several private "helper" methods inside the class that do not require access to any of the class members, and operate solely on their arguments, returning a result.
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
Is there any particular reason to specify computeOne
and computeMore
as static methods - or any particular reason not to?
It is certainly easiest to leave them as non-static, even though they could certainly be static without causing any problems.
java
static
methods
static-methods
avalys
źródło
źródło
Odpowiedzi:
Wolę takie metody pomocnicze
private static
; co wyjaśni czytelnikowi, że nie będą modyfikować stanu obiektu. Moje IDE pokaże również kursywą wywołania metod statycznych, więc będę wiedział, że metoda jest statyczna bez szukania podpisu.źródło
protected static
which makes them testable very easily in a test class in the same package.static
(if we just want it for testing).Może to spowodować nieco mniejszy kod bajtowy, ponieważ metody statyczne nie uzyskają dostępu do
this
. Nie sądzę, żeby miało to jakąkolwiek różnicę w szybkości (a gdyby tak się stało, prawdopodobnie byłby zbyt mały, aby zrobić ogólną różnicę).Uczyniłbym je statycznymi, ponieważ generalnie robię to, jeśli to w ogóle możliwe. Ale to tylko ja.
EDYCJA: Ta odpowiedź wciąż jest lekceważona, być może z powodu bezpodstawnego twierdzenia o rozmiarze kodu bajtowego. Więc faktycznie przeprowadzę test.
Kod bajtowy (pobrany za pomocą
javap -c -private TestBytecodeSize
):Wywołanie metody statycznej wymaga dwóch bajtów (bajtów?):
iconst_0
(Dla argumentu) iinvokestatic
.Wywołanie metody niestatycznej wymaga trzech:
aload_1
(jakTestBytecodeSize
sądzę dla obiektu),iconst_0
(dla argumentu) iinvokespecial
. (Zauważ, że gdyby nie były to metody prywatne, byłoby toinvokevirtual
zamiast tegoinvokespecial
; patrz JLS §7.7 Metody wywoływania ).Teraz, jak powiedziałem, nie oczekuję, że między tymi dwoma
invokestatic
rzeczami będzie jakaś wielka różnica, poza faktem, że wymaga o jeden mniej bajtekodu.invokestatic
iinvokespecial
oba powinny być nieco szybsze niżinvokevirtual
, ponieważ oba używają wiązania statycznego zamiast dynamicznego, ale nie mam pojęcia, czy jedno z nich jest szybsze od drugiego. Nie mogę też znaleźć żadnych dobrych referencji. Najbliżej mogę znaleźć ten artykuł JavaWorld z 1997 roku , który w zasadzie stanowi powtórzenie tego , co właśnie powiedziałem:Ale wiele rzeczy zmieniło się od 1997 roku.
Podsumowując ... Chyba wciąż trzymam się tego, co powiedziałem wcześniej. Szybkość nie powinna być powodem do wybierania jednej z drugiej, ponieważ w najlepszym przypadku byłaby to mikrooptymalizacja.
źródło
Moją osobistą preferencją byłoby deklarowanie ich jako statycznych, ponieważ jest to wyraźna flaga, że są bezpaństwowcami.
źródło
Odpowiedź brzmi ... to zależy.
Jeśli członek jest zmienną instancji specyficzną dla obiektu, z którym mamy do czynienia, to po co w ogóle przekazywać ją jako parametr?
Na przykład:
źródło
Jednym z powodów, dla których warto zadeklarować metody statycznego pomocnika, jest konieczność wywołania ich w konstruktorze klas „przed”
this
lubsuper
. Na przykład:Jest to nieco wymyślony przykład, ale najwyraźniej
recoverInt
nie może być w tym przypadku metodą instancji.źródło
Naprawdę nie mogę wymyślić wyraźnych korzyści dla prywatnej metody statycznej. To powiedziawszy, nie ma też szczególnych zalet, aby uczynić je niestatycznymi. Jest to głównie kwestia prezentacji: możesz ustawić je w sposób statyczny, aby wyraźnie podkreślić fakt, że nie zmieniają obiektu.
W przypadku metody z różnymi uprawnieniami dostępu sądzę, że istnieją dwa główne argumenty:
Poza tym różnica jest dość niewielka i mocno wątpię, że dodatkowa wartość tego wskaźnika przekazanego do metody instancji robi znaczącą różnicę.
źródło
Prawidłowa odpowiedź to:
każda metoda, która nie pobiera żadnych informacji z pola i nie umieszcza żadnych informacji w polu, nie musi być metodą instancji. Każda metoda, która nie używa ani nie zmienia żadnych pól w swojej klasie lub obiekcie, może równie dobrze być metodą statyczną.
źródło
Tak.
Zachowując je jako metody instancji, możesz później zapewnić inną implementację.
Może to zabrzmieć głupio (i faktycznie byłoby tak, gdyby te metody były używane tylko przez ciebie w programie 50-liniowym), ale w większych aplikacjach lub w bibliotekach używanych przez kogoś innego, możesz zdecydować się na lepszą implementację, ale nie chcę złamać istniejący kod.
Tworzysz więc podklasę i zwracasz ją w nowych wersjach, a ponieważ metody zostały zadeklarowane jako metody instancji, pozwalasz polimorfizmowi na wykonanie swojej pracy.
Dodatkowo możesz skorzystać z ustawienia konstruktora na prywatny i zapewnić statyczną metodę fabryczną z tego samego powodu.
Więc moim zaleceniem jest zachowanie ich jako metod instancji i unikanie w miarę możliwości statycznych.
Skorzystaj z dynamizmu, jaki zapewnia język.
Zobacz tutaj nieco pokrewny film: Jak zaprojektować dobry interfejs API i dlaczego ma to znaczenie
Chociaż nie jest to bezpośrednio związane z dyskusją na temat metody „static vs. instance”, dotyczy kilku interesujących punktów w projektowaniu API.
źródło
Jednym z problemów związanych z posiadaniem metod statycznych jest to, że może to utrudnić użycie obiektu w testach jednostkowych . Mockito nie może tworzyć próbnych metod dla metod statycznych i nie można utworzyć implementacji tej podklasy.
źródło
Jeśli metoda jest w zasadzie tylko podprogramem, który nigdy nie będzie w przewidywalny sposób wykorzystywać informacji o stanie, zadeklaruj ją jako statyczną.
Pozwala to na użycie go w innych metodach statycznych lub podczas inicjalizacji klas, tj .:
źródło
Moje preferencje w takich przypadkach jest, aby
computeOne
icomputeMore
metod statycznych. Powód: enkapsulacja. Im mniej kodu ma dostęp do implementacji twojej klasy, tym lepiej.Na przykład dajesz, stwierdzają, że
computeOne
icomputeMore
nie powinny mieć dostęp do wewnętrznych części klasy, dlaczego więc dać szansę na opiekunów klasy mieszać się z wewnętrznych.źródło
Chciałbym wyjaśnić kilka rzeczy, które inni mówili, ponieważ podają nieprawidłowe informacje.
Po pierwsze, ponieważ metody są prywatne, nawet jeśli zadeklarujesz je jako statyczne, nie będziesz mógł uzyskać do nich dostępu poza tą klasą. Po drugie, są prywatne, więc nie można nawet przesłonić podklasy, więc statyczna lub niestatyczna nie robi żadnej różnicy. Po trzecie, od konstruktora klasy można również wywołać niestatystyczną metodę prywatną, nie musi ona być statyczna.
Teraz pojawia się pytanie, czy prywatną metodę pomocniczą należy zdefiniować jako statyczną czy niestatyczną. Pójdę z odpowiedzią Steve'a, ponieważ oznaczenie prywatnej metody statycznej pokazuje, że ta metoda jest bezstanowa, ponieważ przestrzegam tej zasady również podczas kodowania.
źródło
Z doświadczenia powiedziałbym, że takie prywatne metody są na ogół dość uniwersalne i wielokrotnego użytku.
Myślę, że pierwszą rzeczą do zrobienia jest zadanie pytania, czy metoda może być przydatna poza bieżącym kontekstem klasowym. Jeśli tak, zrobiłbym dokładnie to, co sugeruje Każdy, i wyodrębniłbym tę metodę jako statyczną do jakiejś klasy utils, gdzie ktoś, miejmy nadzieję, sprawdzi przed wdrożeniem nowej metody dokładnie to samo.
Takie prywatne metody powszechnego użytku są źródłem dużej części duplikacji kodu w projekcie, ponieważ każdy programista samodzielnie je zmienia na nowo w miejscu, w którym musi go użyć. Tak więc centralizacja takich metod jest dobrym rozwiązaniem.
źródło
Pytanie statyczne / niestatyczne sprowadza się do „czy naprawdę muszę użyć obiektu tej klasy”?
Czy przekazujesz obiekt między różnymi metodami? Czy obiekt zawiera informacje przydatne poza kontekstem metod statycznych? Czy istnieje jakikolwiek powód, aby nie definiować metod w obie strony, jeśli będziesz ich używać w obie strony?
Jeśli jesteś w tym dylemacie, wydaje mi się, że masz wszystkie dane wymagane dla metody unoszące się w kodzie poza obiektem. Czy to jest to, czego chcesz? Czy łatwiej byłoby zawsze zbierać te dane za każdym razem za każdym razem? Możesz być ambiwalentny, jeśli chodzi o wybór jednego modelu. Jeśli możesz to wszystko zrobić w jeden sposób, wybierz statyczny lub niestatyczny i idź z tym.
źródło
Mówiąc dokładniej w podanym przykładzie, wydaje się, że celem zdefiniowania tych metod jest bardziej przejrzystość kodu podczas czytania niż funkcjonalność (są one zdefiniowane jako prywatne). W takim przypadku korzystanie ze statycznego naprawdę nic dla ciebie nie robi, ponieważ celem statycznego jest ujawnienie funkcjonalności klasy.
źródło
Jednym z powodów jest to, że wszystkie pozostałe są równe, statyczne wywołania metod powinny być szybsze. Metody statyczne nie mogą być wirtualne i nie należy domyślnie brać tego odniesienia.
źródło
Jak wiele osób powiedziało, uczyń to statycznym ! Oto zasada, którą stosuję: jeśli uważasz, że metoda jest tylko funkcją matematyczną tj. Jest bezstanowa, nie obejmuje żadnych zmiennych instancji (=> brak zmiennych niebieskiego koloru [w zaćmieniu] w metodzie), a wynik metoda będzie taka sama dla liczby „n” wywołań (przy tych samych parametrach, oczywiście), a następnie oznacz tę metodę jako STATIC.
A jeśli uważasz, że ta metoda będzie przydatna dla innej klasy, przenieś ją do klasy Util, w przeciwnym razie umieść metodę jako prywatną w tej samej klasie. (minimalizacja dostępności)
źródło
Off-Topic: Zachowałbym metody pomocnicze w samodzielnej klasie narzędziowej / pomocniczej z tylko metodami statycznymi.
Problem z posiadaniem metod pomocniczych w punkcie użycia (czytaj „tę samą klasę”) polega na tym, że ktoś z dalszej linii może po prostu opublikować własne niepowiązane metody pomocnicze w tym samym miejscu
źródło
Zaletą prywatnych metod statycznych jest to, że mogą być ponownie wykorzystane później, jeśli zajdzie potrzeba ponownego zainicjowania zmiennej klasy.
źródło
Bez modyfikatora statycznego nie można dowiedzieć się, że metoda jest bezstanowa bez dodatkowej analizy, którą można łatwo wykonać, pisząc (ponownie) metodę.
Wtedy „statyczny” modyfikator może dać ci pomysły na temat refaktoryzacji oprócz innych rzeczy, które inni mogą uznać za nieużyteczne. Np. Przeniesienie metody do jakiejś klasy Utility lub przekonwertowanie jej na metodę członka.
źródło
Zadeklarowałbym je jako statyczne, aby oznaczyć je jako bezpaństwowe.
Java nie ma lepszego mechanizmu dla drobnych operacji, które nie są eksportowane, więc myślę, że prywatna statyczna jest akceptowalna.
źródło