Wywołanie getterów na obiekcie A przechowywanie go jako zmiennej lokalnej (footprint pamięci, wydajność)

W poniższym fragmencie kodu wykonujemy połączenie listType.getDescription() dwa razy:

for (ListType listType: this.listTypeManager.getSelectableListTypes())
{
    if (listType.getDescription() != null)
    {
        children.add(new SelectItem( listType.getId() , listType.getDescription()));
    }
}

Chciałbym refaktorować kod, aby użyć jednej zmiennej:

for (ListType listType: this.listTypeManager.getSelectableListTypes())
{
    String description = listType.getDescription();

    if (description != null)
    {
        children.add(new SelectItem(listType.getId() ,description));
    }
}

Rozumiem, że JVM jest w jakiś sposób zoptymalizowany pod oryginalny kod, a zwłaszcza zagnieżdżanie wywołań, takich jak children.add(new SelectItem(listType.getId(), listType.getDescription()));.

Porównanie dwóch opcji, która z nich jest preferowaną metodą i dlaczego? Chodzi o ślad pamięci, wydajność, czytelność/łatwość i inne, które nie przychodzą mi teraz do głowy.

Kiedy ten ostatni fragment kodu staje się bardziej korzystny w stosunku do pierwszego, to znaczy, czy istnieje (przybliżona) liczba wywołań listType.getDescription(), gdy użycie zmiennej lokalnej temp staje się bardziej pożądane, ponieważ listType.getDescription() zawsze wymaga pewnych operacji stosu do przechowywania obiektu this?

Author: Robert MacLean, 2013-10-18

5 answers

Prawie zawsze wolałabym rozwiązanie zmiennej lokalnej.

Footprint pamięci

Pojedyncza zmienna lokalna kosztuje 4 lub 8 bajtów. To odniesienie i nie ma rekurencji, więc zignorujmy to.

Wydajność

Jeśli jest to prosty getter, JVM może go zapamiętać, więc nie ma różnicy. Jeśli jest to kosztowne połączenie, którego nie można zoptymalizować, ręczne notowanie przyspiesza.

Czytelność

Postępuj zgodnie z zasadą suchego . W Twoim przypadku nie ma to znaczenia, ponieważ nazwa lokalnej zmiennej jest tak długa, jak wywołanie metody, ale dla bardziej skomplikowanych, jest to czytelność, ponieważ nie musisz znaleźć 10 różnic między tymi dwoma wyrażeniami. Jeśli wiesz, że są takie same, wyjaśnij to używając zmiennej lokalnej.

Poprawność

Wyobraź sobie, że twój SelectItem nie akceptuje nulls, a twój program jest wielowątkowy. Wartość listType.getDescription() może się w międzyczasie zmienić, a Ty tosty.

Debugowanie

Posiadanie zmiennej lokalnej zawierającej interesującą wartość jest zaletą.


Jedyną rzeczą do wygrania przez pominięcie zmiennej lokalnej jest zapisanie jednej linii. Więc zrobiłbym to tylko w przypadkach, gdy to naprawdę nie ma znaczenia:

  • bardzo krótkie wyrażenie
  • Brak możliwości jednoczesnej modyfikacji
  • simple private final getter
 29
Author: maaartinus,
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-03 03:18:40

Myślę, że sposób numer dwa jest zdecydowanie lepszy, ponieważ poprawia czytelność i utrzymanie Twojego kodu, co jest tutaj najważniejsze. Tego rodzaju mikro-optymalizacja nie pomoże Ci w niczym, chyba że napiszesz aplikację, w której każda milisekunda jest ważna.

 7
Author: Petr Mensik,
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-10-18 09:11:43

Nie jestem pewien, czy oba są preferowane. To, co ja wolałabym , to wyraźnie czytelny kod niż kod wykonujący, zwłaszcza gdy zysk wydajności jest znikomy. W tym przypadku podejrzewam, że nie ma zauważalnej różnicy (zwłaszcza biorąc pod uwagę optymalizację JVM i możliwości przepisywania kodu)

 2
Author: Brian Agnew,
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-10-18 09:10:54

W kontekście języków imperatywnych wartość zwracana przez wywołanie funkcji nie może być zapamiętana (Zobacz http://en.m.wikipedia.org/wiki/Memoization ), ponieważ nie ma gwarancji, że funkcja nie ma skutków ubocznych. W związku z tym Twoja strategia rzeczywiście unika wywołania funkcji kosztem przydzielenia zmiennej tymczasowej do przechowywania odniesienia do wartości zwracanej przez wywołanie funkcji. Oprócz tego, że jest nieco bardziej wydajny (co tak naprawdę nie ma znaczenia, chyba że funkcja jest wywoływana wiele razy w pętli), wybrałbym Twój styl ze względu na lepszą czytelność kodu.

 1
Author: Tarik,
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-10-18 09:21:08

Zgadzam się z podejściem zmiennej lokalnej do czytelności tylko wtedy, gdy Nazwa zmiennej lokalnej jest samodokumentująca. Nazwanie go "opisem" nie wystarczy (który opis?). Nazwanie go "selectableListTypeDescription" byłoby jasne. Dodałbym, że zmienna przyrostowa w pętli for powinna mieć nazwę "selectableListType"(szczególnie jeśli "listTypeManager" ma Accesory dla innych typów list).

Innym powodem byłoby, gdyby nie gwarancja, że jest to jednowątkowy lub Twoja lista jest niezmienna.

 0
Author: jaywild,
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-03-21 15:39:37