Java: kiedy używać metod statycznych

911

Zastanawiam się, kiedy stosować metody statyczne? Powiedzmy, jeśli mam klasę z kilkoma modułami pobierającymi i ustawiającymi, metodę lub dwie, i chcę, aby te metody były wywoływalne tylko na obiekcie instancji klasy. Czy to oznacza, że ​​powinienem zastosować metodę statyczną?

na przykład

Obj x = new Obj();
x.someMethod

lub

Obj.someMethod

(czy to statyczny sposób?)

Jestem raczej zmieszany!

KP65
źródło

Odpowiedzi:

1458

Jedna praktyczna zasada: zadaj sobie pytanie „Czy sensowne jest wywoływanie tej metody, nawet jeśli żaden obiekt nie został jeszcze zbudowany?” Jeśli tak, zdecydowanie powinien być statyczny.

Więc w klasie Carmożesz mieć metodę:

double convertMpgToKpl(double mpg)

... który byłby statyczny, ponieważ można by chcieć wiedzieć, na co konwertuje 35mpg, nawet jeśli nikt nigdy go nie zbudował Car. Ale ta metoda (która określa wydajność jednego konkretnego Car):

void setMileage(double mpg)

... nie może być statyczny, ponieważ nie jest możliwe wywołanie metody, zanim Carzostanie ona zbudowana.

(Nawiasem mówiąc, odwrotność nie zawsze jest prawdą: czasami możesz mieć metodę, która obejmuje dwa Carobiekty i nadal chcesz, aby była statyczna. Np .:

Car theMoreEfficientOf( Car c1, Car c2 )

Chociaż można to przekonwertować na wersję niestatyczną, niektórzy twierdzą, że skoro nie ma „uprzywilejowanego” wyboru, który Carjest ważniejszy, nie powinieneś zmuszać dzwoniącego do wybrania jednego Carjako obiektu, który wywołasz metoda włączona. Ta sytuacja stanowi jednak niewielki ułamek wszystkich metod statycznych.)

nie-tylko-yeti
źródło
325
Kilka dobrych przykładów tutaj. Dodałbym jednak, że „statyczny” jest często cenny, gdy wiesz, że coś się nie zmieni w różnych instancjach. W takim przypadku naprawdę rozważyłbym „zasadę pojedynczej odpowiedzialności”, która oznacza, że ​​klasa powinna mieć jedną odpowiedzialność, a zatem tylko jeden powód do zmiany. Uważam, że należy rozważyć przeniesienie funkcji „ConvertMpgToKpl (double mpg)” i podobnych metod do ich własnej klasy. Celem obiektu samochodu jest umożliwienie tworzenia wystąpień samochodów, a nie zapewnienie ich porównania. Te powinny być zewnętrzne w stosunku do klasy.
Zack Jannsen,
34
Myślę, że wolałbym metodę Car#isMoreEfficientThan(Car). Ma tę zaletę, że samochód, który zwrócisz w remisie, nie jest arbitralny. Z tytułu metody wynika, co jest zwracane w remisie.
Cruncher
5
Byłbym również ostrożny w tworzeniu metody statycznej, która korzysta z jakiegoś zewnętrznego zasobu (systemu plików, bazy danych itp.). Ten typ statyczny może sprawić, że testowanie metod konsumpcyjnych będzie przerażające. Osobiście staram się utrzymać statykę w dziedzinie „użyteczności”.
Seth M.
7
W rzeczywistości należy go wdrożyć jako komparator .
Dogweather
3
@ B1KMusic Oczywiście. Mam na myśli to, „który samochód jest zwrócony w remisie” to „prawdziwe mapy do wzywanego samochodu i fałszywe mapy do przejechanego samochodu”. To bez dwuznaczności.
Cruncher
538

Zdefiniuj metody statyczne tylko w następujących scenariuszach:

  1. Jeśli piszesz klasy narzędzi i nie należy ich zmieniać.
  2. Jeśli metoda nie używa żadnej zmiennej instancji.
  3. Jeśli jakakolwiek operacja nie zależy od utworzenia instancji.
  4. Jeśli istnieje kod, który może być łatwo współużytkowany przez wszystkie metody instancji, wyodrębnij ten kod do metody statycznej.
  5. Jeśli masz pewność, że definicja metody nigdy nie zostanie zmieniona lub zastąpiona. Ponieważ metody statyczne nie mogą zostać zastąpione.
Mohd
źródło
45
dobre punkty, ale są to wymagania, jeśli chcesz uczynić metodę statyczną, a nie powody, aby ją tworzyć.
tetsuo,
4
@Mohd o wymaganiu 5: Kiedy możesz być w 100% pewien, że metoda nigdy nie zostanie zmieniona lub zastąpiona? Czy nie zawsze istnieją nieznane czynniki, których nie można wziąć pod uwagę w chwili pisania metody statycznej?
PixelPlex,
8
„Klasy użytkowe” są bardzo trudne do uzasadnienia, złą rzeczą jest to, że prędzej czy później wszystko zaczyna „wyglądać” jak narzędzie (tak, mówię o pakiecie „zużytym”, który jest rozdęty, nietykalny i źle przetestowany), a twoje przypadki testowe będą wymagały więcej pracy (aby wyśmiewać statyczne narzędzia to HARD). Najpierw preferuj obiekty.
Sergio,
2
@Mohd tej odpowiedzi właśnie szukam. W przypadku wielowątkowości napotkałem wiele problemów. Czy możesz prosić o rozwinięcie punktów 2, 3 więcej (na przykład 100 kciuki w górę za ciebie)
Prakash Pandey,
Myślę, że należy stworzyć „klasę statyczną”, jeśli zamierzasz używać zmiennych i metod statycznych.
Robert Rocha,
182

Istnieje kilka ważnych powodów, aby używać metod statycznych:

  • Wydajność : jeśli chcesz uruchomić jakiś kod i nie chcesz tworzyć instancji dodatkowego obiektu, umieść go w metodzie statycznej. JVM może również dużo zoptymalizować metody statyczne (myślę, że kiedyś przeczytałem Jamesa Goslinga, który oświadcza, że ​​nie potrzebujesz niestandardowych instrukcji w JVM, ponieważ metody statyczne będą tak samo szybkie, ale nie mogą znaleźć źródła - dlatego to może być całkowicie fałszywe). Tak, to mikrooptymalizacja i prawdopodobnie niepotrzebna. A my programiści nigdy nie robimy niepotrzebnych rzeczy tylko dlatego, że są fajne, prawda?

  • Praktyczność : zamiast dzwonić new Util().method(arg), dzwonić Util.method(arg)lub method(arg)przy imporcie statycznym. Łatwiej, krócej.

  • Dodawanie metod : naprawdę chciałeś, aby klasa String miała removeSpecialChars()metodę instancji, ale jej nie ma (i nie powinna, ponieważ znaki specjalne twojego projektu mogą różnić się od znaków innych projektów) i nie możesz jej dodać (od Java jest trochę rozsądny), więc tworzysz klasę użyteczności i wywołujesz removeSpecialChars(s)zamiast s.removeSpecialChars(). Słodkie.

  • Czystość : zachowując pewne środki ostrożności, twoja metoda statyczna będzie czystą funkcją , to znaczy, jedyne, na czym to zależy, to jej parametry. Dane wejściowe, dane wyjściowe. Jest to łatwiejsze do odczytania i debugowania, ponieważ nie musisz się martwić o dziwactwa związane z dziedziczeniem. Możesz to zrobić również za pomocą metod instancji, ale kompilator pomoże ci nieco bardziej za pomocą metod statycznych (nie zezwalając na odwołania do atrybutów instancji, metody zastępujące itp.).

Będziesz także musiał stworzyć metodę statyczną, jeśli chcesz stworzyć singleton, ale ... nie. Pomyśl dwa razy.

Co ważniejsze, dlaczego nie chcesz stworzyć metody statycznej? Zasadniczo polimorfizm wychodzi z okna . Nie będzie można zastąpić metody ani zadeklarować jej w interfejsie (wcześniejszym niż Java 8) . Projekt wymaga dużej elastyczności. Ponadto, jeśli potrzebujesz stanu , skończysz z wieloma błędami współbieżności i / lub wąskimi gardłami, jeśli nie będziesz ostrożny.

tetsuo
źródło
1
Wymieniono tutaj wiele dobrych powodów, dla których statyczny może być użyteczny. Jeszcze jedno, o czym myślę, to to, że pisanie testów jednostkowych dla takich metod jest po prostu proste
nilesh
@tetsuo Thanks! Twoje wyjaśnienie jest bardzo jasne, a podane powody są bardzo logiczne i mają wiele sensu.
Deniss M.,
3
A my programiści nigdy nie robimy niepotrzebnych rzeczy tylko dlatego, że są fajne, prawda? +1
Scaramouche,
To powiedziawszy, że metoda statyczna staje się pełną funkcją o nazwie stackoverflow.com/questions/155609/...
Ivanzinho
Zgadzam się z wydajnością i praktycznością, ale nie z czystością. Metoda statyczna może modyfikować statyczne elementy klasy (które mogą być prywatne). To może być przydatne. Na przykład, możesz mieć metodę taką jak „static synchronized int divateID () {return idNext ++;}”. W rzeczywistości metoda statyczna może być tak samo czysta lub nieczysta jak metoda niestatyczna pod względem skutków ubocznych.
Adam Gawne-Cain,
42

Po przeczytaniu artykułów Misko uważam, że metody statyczne są złe z testowego punktu widzenia. Zamiast tego powinieneś mieć fabryki (być może przy użyciu narzędzia do wstrzykiwania zależności, takiego jak Guice ).

jak mogę się upewnić, że mam tylko jedno z czegoś

tylko jedno z nich Problem „jak zapewnić, że mam tylko jedno z czegoś” jest miło pominięty. Tworzysz tylko jeden ApplicationFactory w swoim głównym, w wyniku czego tworzysz tylko jedno wystąpienie wszystkich singletonów.

Podstawowym problemem związanym z metodami statycznymi jest to, że są to kod proceduralny

Podstawowym problemem związanym z metodami statycznymi jest to, że są to kod proceduralny. Nie mam pojęcia, jak testować jednostkowy kod proceduralny. Testy jednostkowe zakładają, że mogę utworzyć kopię mojej aplikacji w izolacji. Podczas instancji łączę zależności z próbnymi / towarzyskimi, które zastępują prawdziwe zależności. W programowaniu proceduralnym nie ma nic do „połączenia”, ponieważ nie ma żadnych obiektów, kod i dane są osobne.

Alfred
źródło
20
Nie rozumiem części o tym, że nie mogę przetestować kodu procedury jednostkowej. Czy nie konfigurujesz tylko przypadków testowych, które odwzorowują prawidłowe dane wejściowe na prawidłowe dane wyjściowe przy użyciu metody statycznej wraz z klasą jako „jednostką”?
tjb
2
Możesz to zrobić, aby przetestować te funkcje. Ale podczas korzystania z tych statycznych metod w innych klasach, które chcesz przetestować, uważam, że nie możesz ich sfałszować (kpiny / towarzyskie) ani nic, ponieważ nie możesz utworzyć instancji klasy.
Alfred
4
@Alfred: Proszę spojrzeć na PowerMock, który ma możliwość wyśmiewania metod statycznych. Korzystając z PowerMock, istnieje kilka scenariuszy, jeśli takie istnieją, w których można znaleźć zależności metod, których nie można wyśmiewać.
Carles Sala
7
Możesz testować statykę jednostkową za pomocą PowerMock, jednak wkrótce okaże się, że zabrakło ci miejsca w Permgen (zrobiono to, dostałem koszulkę) i wciąż jest paskudne. Chyba że WIESZ (bazując na co najmniej dekadzie własnego doświadczenia w prawdziwych językach OO, nie migrując z C), NIE ZRÓB TO. Poważnie, najgorszy kod, jaki kiedykolwiek widziałem, pochodził z zastosowania statyki przez wbudowanego programistę iw większości przypadków utknęliśmy z nim na zawsze, a dodanie więcej kodu po prostu jeszcze bardziej zamknęło nas w niemodyfikowalnym monolicie. Luźne sprzęgło: nie, testowalne: ledwo modyfikowalne: NIGDY. Uniknąć!
user1016765
14
Rozumiem trudność testowania metod statycznych zależnych od stanu statycznego. Ale kiedy testujesz bezstanowe metody statyczne, takie jak Math.abs()lub Arrays.sort()nawet metody, do których możesz przekazać wszystkie zależności , nie widzę, jak mogłoby to utrudnić testowanie jednostkowe. Powiedziałbym, że prosta ogólna zasada brzmi: jeśli kiedykolwiek miałbyś powód, by kpić z logiki proceduralnej, to nie poddawaj jej statycznej metodzie. Nigdy nie miałem powodu, żeby się wyśmiewać Arrays.sort()lub Math.abs().
Andy,
36

staticMetoda jest jeden rodzaj metody, która nie wymaga żadnych przedmiotów być inicjowane na to, aby nazwać. Czy zauważyłeś, że staticjest używany w mainfunkcji w Javie? Wykonanie programu zaczyna się od tego momentu bez tworzenia obiektu.

Rozważ następujący przykład:

 class Languages 
 {
     public static void main(String[] args) 
     {
         display();
     }

     static void display() 
     {
         System.out.println("Java is my favorite programming language.");
     }
  }
Zishan
źródło
najlepsza odpowiedź
Yahya
20

Metody statyczne w Javie należą do klasy (a nie jej instancji). Nie używają zmiennych instancji i zwykle pobierają dane wejściowe z parametrów, wykonują na nim działania, a następnie zwracają jakiś wynik. Metody instancji są powiązane z obiektami i, jak sama nazwa wskazuje, mogą używać zmiennych instancji.

Kevin Sylvestre
źródło
12

Nie, metody statyczne nie są powiązane z instancją; należą do klasy. Drugi przykład to metody statyczne; metody instancji są pierwsze.

duffymo
źródło
1
Powinieneś użyć metod statycznych, jeśli nie potrzebujesz manipulacji stanem obiektu.
MastAvalons,
11

Jeśli zastosujesz słowo kluczowe static przy użyciu dowolnej metody, jest to znane jako metoda static.

  1. Metoda statyczna należy do klasy, a nie do obiektu klasy.
  2. Metoda statyczna wywoływana bez potrzeby tworzenia instancji klasy.
  3. Metoda statyczna może uzyskać dostęp do elementu danych statycznych i może zmienić jego wartość.
  4. Dostęp do metody statycznej można uzyskać po prostu za pomocą nazwy statycznej nazwy kropki klasy. . . przykład: Student9.change ();
  5. Jeśli chcesz używać niestatycznych pól klasy, musisz użyć metody niestatycznej.

// Program zmiany wspólnej właściwości wszystkich obiektów (pole statyczne).

class Student9{  
 int rollno;  
 String name;  
 static String college = "ITS";  

 static void change(){  
 college = "BBDIT";  
 }  

 Student9(int r, String n){  
 rollno = r;  
 name = n;  
 }  

 void display (){System.out.println(rollno+" "+name+" "+college);}  

public static void main(String args[]){  
Student9.change();  

Student9 s1 = new Student9 (111,"Indian");  
Student9 s2 = new Student9 (222,"American");  
Student9 s3 = new Student9 (333,"China");  

s1.display();  
s2.display();  
s3.display();  
}  }

O / P: 111 Indyjski BBDIT 222 Amerykański BBDIT 333 Chiny BBDIT

IndianProgrammer1234
źródło
10

Metody statyczne nie są powiązane z instancją, więc nie mogą uzyskać dostępu do żadnych pól niestatycznych w klasie.

Użyłbyś metody statycznej, jeśli metoda nie używa żadnych pól (lub tylko pól statycznych) klasy.

Jeśli używane są jakiekolwiek niestatyczne pola klasy, należy użyć metody niestatycznej.

Carsten
źródło
1
Jasna, krótka i prosta odpowiedź.
Josi
8

Metody statyczne powinny być wywoływane w klasie, metody instancji powinny być wywoływane w instancjach klasy. Ale co to w rzeczywistości oznacza? Oto przydatny przykład:

Klasa samochodu może mieć metodę instancji o nazwie Accelerate (). Możesz przyśpieszyć samochód tylko wtedy, gdy samochód rzeczywiście istnieje (został zbudowany) i dlatego byłaby to metoda instancji.

Klasa samochodu może również mieć metodę count o nazwie GetCarCount (). Zwróciłoby to całkowitą liczbę samochodów wyprodukowanych (lub zbudowanych). Jeśli nie zbudowano żadnego samochodu, ta metoda zwróciłaby 0, ale nadal powinna być możliwa do wywołania, a zatem musiałaby być metodą statyczną.

Charlie Seligman
źródło
6

W rzeczywistości używamy statycznych właściwości i metod w klasie, kiedy chcemy użyć jakiejś części naszego programu, powinna istnieć tam, dopóki nasz program nie zostanie uruchomiony. I wiemy, że do manipulowania właściwościami statycznymi potrzebujemy metod statycznych, ponieważ nie są one częścią zmiennej instancji. Bez metod statycznych manipulowanie właściwościami statycznymi jest czasochłonne.

Sagar
źródło
Utrzymywanie stanu w zmiennych statycznych jest złym posunięciem z wielu powodów - takich jak bezpieczeństwo wielowątkowości, debugowanie, enkapsulacja danych itd. Itp. Metody statyczne są OK, jeśli są czystymi funkcjami (pracuj tylko z parametrami, bez ich zmiany). Dobrym przykładem może być klasa użyteczności, na przykład obliczenia matematyczne.
Vladimir Demirev
5

Użyj metody statycznej, jeśli chcesz mieć dostęp do metody bez wystąpienia klasy.

Jamey
źródło
29
Nie daje to żadnego uzasadnienia dla zaprojektowania programu.
adamjmarkham
4

Statyczny: Obj.someMethod

Użyj, staticgdy chcesz zapewnić dostęp do metody na poziomie klasy, tj. Tam, gdzie metoda powinna być możliwa do wywołania bez wystąpienia klasy.

Finbarr
źródło
4

Metody statyczne nie muszą być wywoływane na obiekcie i wtedy go używasz. Przykład: twoja funkcja Main () jest statyczna i nie tworzysz obiektu do jej wywołania.

Vaishak Suresh
źródło
1
Tak! Zobacz, gdzie przyszedłem, przeglądając pytania Java noobie! To mały świat :-)
Deepak,
1
@ Rzeczywiście mały świat Deepaka :)
Vaishak Suresh
4

Metody statyczne i zmienne są kontrolowaną wersją funkcji i zmiennych „Globalnych” w Javie. W których metodach można uzyskać dostęp jako classname.methodName()lub classInstanceName.methodName(), tj. Metodach statycznych i zmiennych można uzyskać dostęp za pomocą nazwy klasy, a także instancji klasy.

Klasy nie można zadeklarować jako statyczną (ponieważ nie ma to sensu. Jeśli klasa jest zadeklarowana publicznie, można uzyskać do niej dostęp z dowolnego miejsca), klasy wewnętrzne można zadeklarować jako statyczne.

Manju Yadav
źródło
3

Można zastosować metody statyczne, jeśli

  • Nie chce się wykonywać akcji na instancji (metody narzędziowe)

    Jak wspomniano w kilku powyższych odpowiedziach w tym poście, przeliczanie mil na kilometry lub obliczanie temperatury z Fahrenheita na stopnie Celsjusza i odwrotnie. W tych przykładach przy użyciu metody statycznej nie trzeba tworzyć instancji całego nowego obiektu w pamięci sterty. Rozważ poniżej

    1. new ABCClass(double farenheit).convertFarenheitToCelcium() 
    2. ABCClass.convertFarenheitToCelcium(double farenheit)

    pierwsza z nich tworzy nową klasę dla każdej wywołanej metody, Performance, Practical . Przykładami są klasa Math i Apache-Commons poniżej klasa StringUtils:

    Math.random()
    Math.sqrt(double)
    Math.min(int, int)
    StringUtils.isEmpty(String)
    StringUtils.isBlank(String)
  • Chcemy użyć jako prostej funkcji. Dane wejściowe są jawnie przekazywane, a dane wynikowe są zwracane. Dziedziczenie, instanalizacja obiektu nie wchodzi w grę. Zwięzły, czytelny .

UWAGA : Niewielu ludzi sprzeciwia się testowalności metod statycznych, ale metody statyczne można również przetestować! Za pomocą jMockit można kpić z metod statycznych. Testability . Przykład poniżej:

new MockUp<ClassName>() {
    @Mock
    public int doSomething(Input input1, Input input2){
        return returnValue;
    }
};
Amit Kaneria
źródło
3

Metody statyczne to metody w Javie, które można wywoływać bez tworzenia obiektu klasy. Należy do klasy.

Używamy metody statycznej, gdy nie trzeba wywoływać metody przy użyciu instancji.

rashedcs
źródło
2

Zastanawiam się, kiedy stosować metody statyczne?

  1. Częstym zastosowaniem staticmetod jest dostęp do staticpól.
  2. Ale możesz mieć staticmetody bez odwoływania się do staticzmiennych. Metody pomocnicze bez odwoływania się do staticzmiennej można znaleźć w niektórych klasach Java, takich jak java.lang.Math

    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }
  3. Innym przypadkiem użycia, mogę pomyśleć o tych metodach w połączeniu z synchronizedmetodą jest implementacja blokowania na poziomie klasy w środowisku wielowątkowym.

Powiedzmy, jeśli mam klasę z kilkoma modułami pobierającymi i ustawiającymi, metodę lub dwie, i chcę, aby te metody były wywoływalne tylko na obiekcie instancji klasy. Czy to oznacza, że ​​powinienem zastosować metodę statyczną?

Jeśli potrzebujesz uzyskać dostęp do metody na obiekcie instancji klasy, twoja metoda powinna być niestatyczna.

Strona dokumentacji Oracle zawiera więcej szczegółów.

Nie wszystkie kombinacje zmiennych i metod instancji i klas są dozwolone:

  1. Metody instancji mogą uzyskiwać bezpośredni dostęp do zmiennych instancji i metod instancji.
  2. Metody instancji mogą uzyskiwać bezpośredni dostęp do zmiennych klas i metod klas.
  3. Metody klas mogą bezpośrednio uzyskiwać dostęp do zmiennych klas i metod klas.
  4. Metody klas nie mają bezpośredniego dostępu do zmiennych instancji lub metod instancji - muszą używać odwołania do obiektu. Ponadto metody klas nie mogą używać tego słowa kluczowego, ponieważ nie ma instancji, do której można by się odwoływać.
Ravindra babu
źródło
Czy nie możemy uzyskać dostępu do pól statycznych za pomocą zwykłych metod? To A common use for static methods is to access static fields.nie jest argument.
parsecer
2

Metoda statyczna ma dwa główne cele:

  1. Do metod narzędziowych lub pomocniczych, które nie wymagają stanu obiektu. Ponieważ nie ma potrzeby uzyskiwania dostępu do zmiennych instancji, posiadanie metod statycznych eliminuje potrzebę wywoływania przez instancję wywołującą obiektu tylko do wywołania metody.
  2. Dla stanu współdzielonego przez wszystkie instancje klasy, jak licznik. Wszystkie wystąpienia muszą mieć ten sam stan. Metody, które jedynie wykorzystują ten stan, powinny być również statyczne.
hemanto
źródło
1

W Eclipse możesz włączyć ostrzeżenie, które pomaga wykryć potencjalne metody statyczne. (Powyżej podświetlonej linii znajduje się kolejna, o której zapomniałem zaznaczyć)

ustawienie zaćmienia

ave4496
źródło
0

Ilekroć nie chcesz tworzyć obiektu w celu wywołania metody w kodzie, po prostu zadeklaruj tę metodę jako statyczną. Ponieważ metoda statyczna nie wymaga wywołania instancji, ale w tym przypadku catch nie wszystkie metody statyczne są wywoływane automatycznie przez JVM. Z tego przywileju korzysta tylko metoda main () „public static void main [String ... args]” w Javie, ponieważ w środowisku wykonawczym jest to metoda Signature public „static” void main [] poszukiwana przez JVM jako punkt wejścia do rozpocznij wykonywanie kodu.

Przykład:

public class Demo
{
   public static void main(String... args) 
   {
      Demo d = new Demo();

      System.out.println("This static method is executed by JVM");

     //Now to call the static method Displ() you can use the below methods:
           Displ(); //By method name itself    
      Demo.Displ(); //By using class name//Recommended
         d.Displ(); //By using instance //Not recommended
   }

   public static void Displ()
   {
      System.out.println("This static method needs to be called explicitly");
   }
} 

Dane wyjściowe: - Ta metoda statyczna jest wykonywana przez JVM Ta metoda statyczna musi zostać wywołana jawnie Ta metoda statyczna musi zostać wywołana jawnie Ta metoda statyczna musi zostać wywołana jawnie

Amrit
źródło