java jak droga jest metoda

Jestem początkujący i zawsze czytałem, że nie jest dobrze powtarzać kod. Wydaje się jednak, że aby tego nie zrobić, musisz mieć Zwykle dodatkowe wywołania metody. Powiedzmy, że mam następującą klasę

public class BinarySearchTree<E extends Comparable<E>>{
    private BinaryTree<E> root;
    private final BinaryTree<E> EMPTY = new BinaryTree<E>();
    private int count;
    private Comparator<E> ordering;

    public BinarySearchTree(Comparator<E> order){
        ordering = order;
        clear();
    }

    public void clear(){
        root = EMPTY;
        count = 0;
    }
}

Czy byłoby bardziej optymalne dla mnie skopiowanie i wklejenie dwóch linii w mojej metodzie clear() do konstruktora zamiast wywołania rzeczywistej metody? Jeśli tak, to jaka to różnica? Co by było gdyby mój konstruktor wykonał 10 wywołań metody Z Każdym po prostu ustawiając zmienna instancji do wartości? Jaka jest najlepsza praktyka programowania?

Author: Vineet Reynolds, 2011-06-27

12 answers

Czy byłoby bardziej optymalne dla mnie skopiowanie i wklejenie dwóch linii w mojej metodzie clear() do konstruktora zamiast wywołania rzeczywistej metody?

Kompilator może wykonać tę optymalizację. Podobnie jak JVM. Terminologia używana przez autorów kompilatorów i JVM to "inline expansion".

Jeśli tak, to jaka to różnica?

Zmierz to. Często przekonasz się, że to nie robi różnicy. A jeśli uważasz, że jest to hotspot wydajności, szukasz w niewłaściwym miejscu, dlatego musisz go zmierzyć.

Co by było, gdyby mój konstruktor wykonał 10 wywołań metody, z których każda po prostu ustawia zmienną instancji na wartość?

Ponownie, zależy to od wygenerowanego kodu bajtowego i wszelkich optymalizacji wykonywanych przez maszynę Wirtualną Java. Jeśli kompilator/JVM może wbudować wywołania metod, wykona optymalizację, aby uniknąć narzutu tworzenia nowych ramek stosu w runtime.

Jaka jest najlepsza praktyka programowania?

Unikanie przedwczesnej optymalizacji. Najlepszą praktyką jest pisanie czytelnego i dobrze zaprojektowanego kodu, a następnie optymalizacja pod kątem hotspotów wydajności w aplikacji.

 63
Author: Vineet Reynolds,
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
2015-07-06 10:32:10

To, co inni mówili o optymalizacji, jest absolutną prawdą.

Nie ma powodu z punktu widzenia wydajności, aby wprowadzić metodę. Jeśli jest to problem z wydajnością, JIT w JVM będzie go wbudowywać. W Javie wywołania metod są tak bliskie wolności, że nie warto o tym myśleć.

To powiedziawszy, tu jest inny problem. Jest to metoda, która nie jest w pełni zgodna z zasadami programowania.]}, static, lub private) od konstruktora. (Effective Java, 2nd Ed., str. 89 w punkcie zatytułowanym "wzór i dokument dziedziczenia lub jego zakaz")

Co się stanie, jeśli ktoś doda podklasę BinarySearchTree o nazwie LoggingBinarySearchTree, która nadpisuje wszystkie publiczne metody kodem takim jak:

public void clear(){
  this.callLog.addCall("clear");
  super.clear();
}

Wtedy LoggingBinarySearchTree nigdy nie będzie konstruktywny! Problem polega na tym, że this.callLog będzie null, gdy konstruktor BinarySearchTree będzie uruchomiony, ale clear, który zostanie wywołany, jest nadpisany i otrzymasz NullPointerException.

Zauważ, że Java i C++ różnią się tutaj: w C++ konstruktor klasy nadrzędnej, który wywołuje metodę virtual, kończy wywołanie metody zdefiniowanej w klasie nadrzędnej, a nie nadpisanej. Ludzie przełączający się między tymi dwoma językami czasami o tym zapominają.

Biorąc to pod uwagę, wydaje mi się, że w Twoim przypadku lepiej jest wstawić metodę clear wywołaną z konstruktora, ale ogólnie w Javie powinieneś wykonywać wszystkie wywołania metody, które chcesz.

 16
Author: Daniel Martin,
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
2011-06-27 15:37:33

Zdecydowanie zostawiłbym to tak, jak jest. Co jeśli zmienisz clear() logikę? Byłoby niepraktyczne znaleźć wszystkie miejsca, w których skopiowałeś 2 linijki kodu.

 5
Author: Marcelo,
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
2011-06-27 15:15:14

Najlepszą praktyką jest mierzenie dwa razy i cięcie raz.

Gdy zmarnujesz czas na optymalizację, nigdy nie odzyskasz go ponownie! (Więc najpierw zmierz go i zadaj sobie pytanie, czy warto go optymalizować. Ile rzeczywistego czasu zaoszczędzisz?)

W tym przypadku maszyna wirtualna Java prawdopodobnie już wykonuje optymalizację, o której mówisz.

 3
Author: Arafangion,
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
2011-06-27 15:15:23

koszt wywołania metody polega na utworzeniu (i usunięciu) ramki stosu i dodatkowych wyrażeń kodu bajtowego, jeśli trzeba przekazać wartości do metody.

 2
Author: Andreas_D,
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
2011-06-27 15:18:28

Ogólnie rzecz biorąc (a jako początkujący oznacza to zawsze!) nigdy nie powinieneś robić mikro-optymalizacji, jak ta, którą rozważasz. Zawsze preferuj czytelność kodu nad takimi rzeczami.

Dlaczego? Ponieważ kompilator / hotspot dokona tego rodzaju optymalizacji dla Ciebie w locie, i wiele, wiele więcej. Jeśli już, kiedy spróbujesz dokonać optymalizacji wzdłuż tego rodzaju linii (choć nie w tym przypadku) prawdopodobnie spowolnisz działanie. Hotspot rozumie wspólne idiomy programistyczne, jeśli sam spróbujesz tej optymalizacji to pewnie nie zrozumie co próbujesz zrobić, więc nie będzie w stanie tego zoptymalizować.

Jest też dużo większy koszt utrzymania. Jeśli zaczniesz powtarzać kod, to będzie to o wiele więcej wysiłku w utrzymaniu, co prawdopodobnie będzie o wiele więcej kłopotów niż mogłoby się wydawać!

Na marginesie, możesz dostać się do pewnych punktów w swoim życiu programistycznym, w których musisz dokonać niskiej optymalizacji poziomu - ale jeśli trafisz na te punkty, na pewno, na pewno wiesz, kiedy nadejdzie czas. A jeśli nie, zawsze możesz wrócić i zoptymalizować później, jeśli zajdzie taka potrzeba.

 2
Author: Michael Berry,
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-11-10 22:04:17

Wzorcem, który podążam, jest to, czy ta metoda, o której mowa, spełniłaby jedno z następujących kryteriów:

  • czy byłoby pomocne, aby ta metoda była dostępna poza tą klasą?
  • czy byłoby pomocne, aby ta metoda była dostępna w innych metodach?
  • Czy byłoby frustrujące przepisywanie tego za każdym razem, gdy tego potrzebowałem? Czy można zwiększyć wszechstronność metody za pomocą kilku parametrów?

Jeśli któraś z powyższych jest prawdziwa, to powinien być owinięty własną metodą.

 1
Author: Peaches491,
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
2011-06-27 15:16:34

Zachowaj metodę clear(), gdy poprawia czytelność. Posiadanie niezarządzalnego kodu jest droższe.

 1
Author: Fabian Barney,
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
2011-06-27 15:17:19

Optymalizacja kompilatorów zwykle wykonuje całkiem dobrą robotę, usuwając redundancję z tych "dodatkowych" operacji; w wielu przypadkach różnica między" zoptymalizowanym " kodem a kodem pisanym po prostu tak, jak chcesz i uruchamianym przez optymalizujący kompilator jest Żadna; to znaczy, optymalizujący kompilator zwykle wykonuje tak samo dobrą pracę, jak ty, i robi to bez powodowania degradacji kodu źródłowego. W rzeczywistości, wielokrotnie" ręcznie zoptymalizowany " kod kończy się mniej wydajny, ponieważ kompilator bierze pod uwagę wiele rzeczy podczas optymalizacji. Pozostaw swój kod w czytelnym formacie i nie martw się o optymalizację do późniejszego czasu.

" przedwczesna optymalizacja jest podstawą całe zło."- Donald Knuth

 1
Author: Paul Sonier,
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
2011-06-27 15:18:11

Nie martwiłbym się tak bardzo wywołaniem metody, ale logiką metody. Gdyby to były systemy krytyczne, a system musiał "być szybki" wtedy, spojrzałbym na optymalizację kodów, która trwa długo do wykonania.

 0
Author: Buhake Sindi,
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
2011-06-27 15:18:41

Biorąc pod uwagę pamięć nowoczesnych komputerów jest to bardzo tanie. Zawsze lepiej jest podzielić kod na metody, aby ktoś mógł szybko odczytać, co się dzieje. Pomoże to również w zawężeniu błędów w kodzie, jeśli błąd jest ograniczony do jednej metody z ciałem kilku linii.

 0
Author: adamjmarkham,
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
2011-06-27 15:20:03

Jak powiedzieli inni, koszt wywołania metody jest trywialny-do-nada, ponieważ kompilator zoptymalizuje go dla Ciebie.

To powiedziawszy, istnieją niebezpieczeństwa w wywoływaniu metod do instancji z konstruktora. Istnieje ryzyko późniejszej aktualizacji metody instancji, aby mogła ona próbować użyć zmiennej instancji, która nie została jeszcze zainicjowana przez konstruktor. Oznacza to, że niekoniecznie chcesz oddzielić działania budowlane od konstruktora.

Inny pytanie--twoja metoda clear () ustawia root na EMPTY, który jest inicjowany podczas tworzenia obiektu. Jeśli dodasz węzły do EMPTY, a następnie wywołasz clear (), nie będzie resetowania węzła głównego. Tego chcesz?

 0
Author: Matthew Flynn,
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
2011-06-27 15:38:54