Jaki jest zysk z zadeklarowania metody jako statycznej

Ostatnio przeglądałem moje ostrzeżenia W Eclipse i natknąłem się na to:

Ostrzeżenie statyczne

Wyświetli ostrzeżenie kompilatora, jeśli metoda może być zadeklarowana jako statyczna.

[edit] dokładny cytat w Pomocy Eclipse, z naciskiem na prywatne i końcowe:

Po włączeniu kompilator wyda błąd lub ostrzeżenie dla metody, które są prywatne lub końcowe i które odnoszą się tylko do statycznych członków.

Tak Wiem, że mogę go wyłączyć, ale chcę poznać powód jego włączenia?

Dlaczego warto deklarować każdą możliwą metodę jako statyczną?

Czy to da jakieś korzyści? (w domenie mobilnej)

Wskazując metodę jako statyczną, przypuszczam, że pokazuje, że nie używasz żadnych zmiennych instancji, dlatego można je przenieść do klasy stylu utils?

Pod koniec dnia powinienem wyłączyć to "ignoruj", czy powinienem naprawić 100 + ostrzeżeń, które mi dał?

Czy uważasz, że to tylko dodatkowe słowa kluczowe, które brudne Kod, ponieważ kompilator i tak po prostu wprowadzi te metody? (podobnie jak nie deklarujesz każdej zmiennej, którą możesz zakończyć , ale możesz ).

Author: Maarten Bodewes, 2012-06-28

9 answers

Ilekroć piszesz metodę, wypełniasz umowę w danym zakresie. Im węższy jest zakres, tym mniejsza szansa, że napiszesz błąd.

Gdy metoda jest statyczna, nie możesz uzyskać dostępu do elementów niestatycznych; stąd twój zakres jest węższy. Więc, jeśli nie potrzebujesz i nigdy nie będzie potrzebne (nawet w podklasach) Członkowie niestatyczni aby spełnić swoją umowę, po co dawać dostęp do tych pól swojej metodzie? Deklarowanie metody static w tym przypadku pozwoli kompilatorowi sprawdź, czy nie używasz członków, których nie zamierzasz używać.

A co więcej, pomoże to ludziom odczytującym Twój kod zrozumieć charakter umowy.

Dlatego dobrze jest zadeklarować metodę static, gdy faktycznie realizuje statyczny kontrakt.

W niektórych przypadkach twoja metoda oznacza tylko coś w stosunku do instancji twojej klasy i zdarza się, że jej implementacja nie używa żadnego niestatycznego pola lub instancji. W takich przypadkach nie zaznacza metody static.

Przykłady, gdzie nie można użyć słowa kluczowego static:

    Hak rozszerzeń, który nic nie robi (ale może zrobić coś z danymi instancji w podklasie)
  • bardzo proste domyślne zachowanie, które można dostosować w podklasie.
  • implementacja obsługi zdarzenia: implementacja będzie się różnić w zależności od klasy obsługi zdarzenia, ale nie będzie używać żadnej właściwości instancji obsługi zdarzenia.
 129
Author: Samuel Rossille,
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 22:52:07

Nie ma tu pojęcia o optymalizacji.

A static metoda jest static, ponieważ jawnie deklarujesz, że metoda nie opiera się na żadnej instancji klasy zamkniętej tylko dlatego, że nie musi. Tak więc ostrzeżenie o zaćmieniu, jak podano w dokumentacji:

Po włączeniu, kompilator wyda błąd lub ostrzeżenie dla metod, które są prywatne lub końcowe i które odnoszą się tylko do statycznych członków.

Jeśli nie potrzebujesz żadnej zmiennej instancji, a twoja metoda jest prywatna (nie może być wywołana z zewnątrz) lub ostateczna (nie może być nadpisana), wtedy nie ma powodu, aby pozwolić, aby była to normalna metoda zamiast statycznej. Statyczna metoda jest z natury bezpieczniejsza nawet dlatego, że możesz robić z nią mniej rzeczy (nie potrzebuje żadnej instancji, nie masz żadnego implicit this object).

 12
Author: Jack,
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-12 14:23:42

Nie mam informacji na temat wydajności, przypuszczam, że jest to co najwyżej nieznacznie lepsze, ponieważ kod nie musi wykonywać dynamicznej wysyłki w oparciu o Typ.

Jednak znacznie silniejszym argumentem przeciwko refaktoryzacji metod statycznych jest to, że obecnie używanie metod statycznych jest uważane za złą praktykę. Statyczne metody / zmienne nie integrują się dobrze z językiem zorientowanym obiektowo, a także trudno je poprawnie przetestować. Jest to powód, dla którego niektóre nowsze języki rezygnują z pojęcia statycznego metody / zmienne w ogóle, lub spróbuj internalizować je w języku w sposób, który lepiej gra z OO (np. obiekty w Scali).

W większości przypadków potrzebujesz metod statycznych do implementacji funkcji, które używają tylko parametrów jako danych wejściowych i wytwarzają dane wyjściowe za pomocą tego (np. funkcje narzędziowe/pomocnicze) we współczesnych językach istnieje koncepcja funkcji pierwszej klasy, która na to pozwala, więc statyczna nie jest potrzebna. Java 8 będzie miała wbudowane wyrażenia lambda, więc przechodzimy do tego kierunek już.

 6
Author: Istvan Devai,
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-06-28 08:00:01

1. deklarowanie metody static daje niewielkie korzyści wydajnościowe, ale co bardziej użyteczne, pozwala używać jej bez konieczności posiadania instancji obiektu pod ręką(pomyśl na przykład o metodzie fabrycznej lub uzyskaniu Singletona). Służy również celowi dokumentacyjnemu, polegającemu na określeniu charakteru metody. Ten cel dokumentacyjny nie powinien być ignorowany, ponieważ daje natychmiastową wskazówkę na temat charakteru metody czytelnikom kodu i użytkownikom API, a także służy jako narzędzie do myślenie dla oryginalnego programisty-bycie wyraźnym co do zamierzonego znaczenia pomaga również myśleć prosto i produkować kod lepszej jakości(myślę, że bazując na moim osobistym doświadczeniu, ale ludzie są różni). Na przykład, logiczne i dlatego pożądane jest rozróżnienie między metodami operującymi na typie a metodami działającymi na instancji typu (jak zauważył Jon Skeet w komentarzu do pytania C# ).

Kolejnym przypadkiem użycia metod {[0] } jest naśladowanie interfejs programowania proceduralnego. Pomyśl o java.lang.System.println() klasy oraz metod i atrybutów w niej zawartych. Klasa java.lang.System jest używana jako przestrzeń nazw grupowania, a nie instancjonalny obiekt.

2. skąd Eclipse (lub jakikolwiek inny programowany lub inny rodzaj - biokompozytowej lub nie-biokompozytowej - jednostki) może wiedzieć na pewno, która metoda może być zadeklarowana jako statyczna? Nawet jeśli klasa bazowa nie ma dostępu do zmiennych instancji ani nie wywołuje niestatycznych metod, za pomocą mechanizmu dziedziczenie rzeczy mogą się zmienić. Tylko jeśli metoda nie może być nadpisana przez dziedziczenie podklasy, możemy ze 100% pewnością stwierdzić, że metoda naprawdę może być zadeklarowana static. Nadpisanie metody jest niemożliwe dokładnie w dwóch przypadkach bycia

  1. private (Żadna podklasa nie może używać go bezpośrednio i nawet w zasadzie o nim nie wie), lub
  2. final (nawet jeśli jest dostępna przez podklasę, nie ma możliwości zmiany metody, aby odwoływać się do danych instancji lub funkcje).

Stąd logika opcji Eclipse.

3. oryginalny plakat również pyta: "wskazując metodę jako statyczną, przypuszczam, że pokazuje, że nie używasz żadnych zmiennych instancji, dlatego można przenieść do klasy stylu utils? " to bardzo dobra uwaga. Czasami tego rodzaju zmiana projektu jest wskazywana przez Ostrzeżenie.

Jest to bardzo przydatna opcja, którą osobiście bym włączył, gdybym użył Eclipse i do programowania w Javie.

 3
Author: FooF,
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 12:17:43

Zobacz odpowiedź Samuela na temat zmian zakresu metody. Myślę, że jest to główny aspekt statycznej metody.

Pytałeś też o wydajność:

Może być mały przyrost wydajności, ponieważ wywołanie statycznej metody nie wymaga ukrytego odniesienia "this" jako parametru.

Jednak ten wpływ na wydajność jest naprawdę niewielki. Dlatego chodzi o zakres.

 1
Author: Black,
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-06-28 07:56:31

Z wytycznych dotyczących wydajności Androida:

Preferuj statyczne niż wirtualne, jeśli nie potrzebujesz dostępu do obiektów fields, uczyń swoją metodę statyczną. Inwokacje będą wynosić około 15% -20% szybciej. Jest to również dobra praktyka, ponieważ można stwierdzić z metody podpis, że wywołanie metody nie może zmienić stanu obiektu.

Http://developer.android.com/training/articles/perf-tips.html#PreferStatic

 1
Author: Blundell,
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-07-17 15:12:47

Cóż, dokumentacja zaćmienia mówi o tym ostrzeżeniu:

Metoda może być statyczna

Po włączeniu kompilator wyda błąd lub ostrzeżenie dla metody, które są prywatne lub ostateczne i które odnoszą się tylko do statycznych członkowie

Myślę, że to wszystko mówi. Jeśli metoda jest prywatna i ostateczna i odnosi się tylko do elementów statycznych, metoda ta może być równie dobrze zadeklarowana jako statyczna i przez to, należy zauważyć, że zamierzamy tylko uzyskać dostęp do statycznych treści z niego.

Szczerze mówiąc, nie wydaje mi się, aby był to jakiś inny tajemniczy powód.

 0
Author: Edwin Dalorzo,
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-03 19:53:52

Brakowało mi kilku liczb na różnice prędkości. Więc próbowałem je porównywać, co okazało się nie takie proste: pętla Javy staje się wolniejsza po niektórych uruchomieniach / JIT ' s fault?

W końcu użyłem Calipera i wyniki są takie same jak ręczne przeprowadzanie testów:

Nie ma mierzalnej różnicy dla wywołań statycznych/dynamicznych. przynajmniej nie dla Linuksa / AMD64 / Java7.

Wyniki Caliper są tutaj: https://microbenchmarks.appspot.com/runs/1426eac9-36ca-48f0-980f-0106af064e8f#r:scenario.benchmarkSpec.methodName,scenario.vmSpec.options.CMSLargeCoalSurplusPercent,scenario.vmSpec.options.CMSLargeSplitSurplusPercent,scenario.vmSpec.options.CMSSmallCoalSurplusPercent,scenario.vmSpec.options.CMSSmallSplitSurplusPercent,scenario.vmSpec.options.FLSLargestBlockCoalesceProximity,scenario.vmSpec.options.G1ConcMarkStepDurationMillis

A moje własne wyniki to:

Static: 352 ms
Dynamic: 353 ms
Static: 348 ms
Dynamic: 349 ms
Static: 349 ms
Dynamic: 348 ms
Static: 349 ms
Dynamic: 344 ms

The Klasa testowa zacisku to:

public class TestPerfomanceOfStaticMethodsCaliper extends Benchmark {

    public static void main( String [] args ){

        CaliperMain.main( TestPerfomanceOfStaticMethodsCaliper.class, args );
    }

    public int timeAddDynamic( long reps ){
        int r=0;
        for( int i = 0; i < reps; i++ ) {
            r |= addDynamic( 1, i );
        }
        return r;
    }

    public int timeAddStatic( long reps ){
        int r=0;
        for( int i = 0; i < reps; i++ ) {
            r |= addStatic( 1, i );
        }
        return r;
    }

    public int addDynamic( int a, int b ){

        return a+b;
    }

    private static int addStatic( int a, int b ){

        return a+b;
    }

}

A moja klasa testowa to:

public class TestPerformanceOfStaticVsDynamicCalls {

    private static final int RUNS = 1_000_000_000;

    public static void main( String [] args ) throws Exception{

        new TestPerformanceOfStaticVsDynamicCalls().run();
    }

    private void run(){

        int r=0;
        long start, end;

        for( int loop = 0; loop<10; loop++ ){

            // Benchmark

            start = System.currentTimeMillis();
            for( int i = 0; i < RUNS; i++ ) {
                r += addStatic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Static: " + ( end - start ) + " ms" );

            start = System.currentTimeMillis();
            for( int i = 0; i < RUNS; i++ ) {
                r += addDynamic( 1, i );
            }
            end = System.currentTimeMillis();
            System.out.println( "Dynamic: " + ( end - start ) + " ms" );

            // Do something with r to keep compiler happy
            System.out.println( r );

        }

    }

    private int addDynamic( int a, int b ){

        return a+b;
    }

    private static int addStatic( int a, int b ){

        return a+b;
    }

}
 0
Author: Scheintod,
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-07-22 16:07:05

Metody, które możesz zadeklarować jako statyczne, to te, które nie wymagają tworzenia instancji, takie jak

public class MyClass
{
    public static string InvertText(string text)
    {
        return text.Invert();
    }
}

Które można następnie w zamian wywołać w dowolnej innej klasie bez instancjowania tej klasy.

public class MyClassTwo
{
    public void DoSomething()
    {
        var text = "hello world";
        Console.Write(MyClass.InvertText(text));
    }
}

... Ale to pewnie już wiesz. Nie daje to żadnych realnych korzyści jako takich, poza wyjaśnieniem, że metoda nie używa żadnych zmiennych instancji.

Innymi słowy, najbezpieczniej można go całkowicie wyłączyć. Jeśli wiesz nigdy nie użyjesz metody w innych klasach (w tym przypadku powinna być po prostu prywatna), nie potrzebujesz jej w ogóle, aby była statyczna.
 -2
Author: NeroS,
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-08 08:40:43