Zakres zmiennych lokalnych powinien zawsze być możliwie najmniejszy.
W twoim przykładzie zakładam, że niestr
jest używany poza pętlą, w przeciwnym razie nie zadajesz pytania, ponieważ zadeklarowanie go w pętli nie byłoby opcją, ponieważ nie skompilowałoby się.while
while
A zatem, ponieważ niestr
jest używany poza pętlą, najmniejszy możliwy zakres dla znajduje się w pętli while.str
Tak więc odpowiedź jest zdecydowanie, że str
absolutnie należy zadeklarować w pętli while. Bez ifs, bez ands, bez ale.
Jedynym przypadkiem, w którym zasada ta może zostać naruszona, jest to, że z jakiegoś powodu niezwykle ważne jest, aby każdy cykl zegara był wyciskany z kodu, w którym to przypadku możesz rozważyć utworzenie instancji czegoś w zakresie zewnętrznym i ponowne użycie go zamiast ponowne utworzenie go przy każdej iteracji zakresu wewnętrznego. Nie dotyczy to jednak twojego przykładu ze względu na niezmienność ciągów w Javie: nowa instancja str będzie zawsze tworzona na początku twojej pętli i będzie musiała zostać wyrzucona na jej końcu, więc tam nie ma tam możliwości optymalizacji.
EDYCJA: (wstawiam mój komentarz poniżej w odpowiedzi)
W każdym razie właściwym sposobem jest poprawne napisanie całego kodu, ustalenie wymagań dotyczących wydajności produktu, porównanie produktu końcowego z tym wymaganiem, a jeśli nie spełnia tego warunku, optymalizacja. I zwykle dzieje się tak, że w kilku miejscach można znaleźć dobre i formalne optymalizacje algorytmiczne, które sprawiają, że nasz program spełnia wymagania dotyczące wydajności, zamiast konieczności przeglądania całej bazy kodu oraz poprawiania i hakowania aby wycisnąć cykle zegara tu i tam.
Porównałem bajtowy kod tych dwóch (podobnych) przykładów:
Spójrzmy na 1. przykład :
po
javac Test.java
,javap -c Test
otrzymasz:Spójrzmy na 2. przykład :
po
javac Test.java
,javap -c Test
otrzymasz:Obserwacje pokazują, że nie ma różnicy między tymi dwoma przykładami. Jest to wynik specyfikacji JVM ...
Jednak w imię najlepszej praktyki kodowania zaleca się zadeklarowanie zmiennej w możliwie najmniejszym zakresie (w tym przykładzie znajduje się ona w pętli, ponieważ jest to jedyne miejsce, w którym zmienna jest używana).
źródło
final
kochankowie: deklarowaniestr
jakfinal
winside
przypadku paczki również nie ma znaczenia =)Deklarowanie obiektów w najmniejszym zakresie poprawia czytelność .
Wydajność nie ma znaczenia dla dzisiejszych kompilatorów. (W tym scenariuszu)
Z punktu widzenia konserwacji druga opcja jest lepsza.
Deklaruj i inicjalizuj zmienne w tym samym miejscu, w możliwie najwęższym zakresie.
Jak powiedział Donald Ervin Knuth :
tj. sytuacja, w której programista pozwala, aby względy wydajności wpływały na projekt fragmentu kodu. Może to spowodować, że projekt jest nie tak czysty, jak to mogło być albo kod, który jest nieprawidłowy, ponieważ kod jest skomplikowane przez optymalizację i programista jest rozproszony przez optymalizację .
źródło
jeśli chcesz używać także
str
poza looop; ogłosić to na zewnątrz. w przeciwnym razie druga wersja jest w porządku.źródło
Przejdź do zaktualizowanej odpowiedzi ...
Dla tych, którym zależy na wydajności, wyjmij System.out i ogranicz pętlę do 1 bajtu. Używając podwójnego (test 1/2) i ciąg (3/4), czasy, które upłynęły w milisekundach, podano poniżej dla Windows 7 Professional 64 bit i JDK-1.7.0_21. Kody bajtowe (podane również poniżej dla testu 1 i testu 2) nie są takie same. Byłem zbyt leniwy, by testować zmienne i stosunkowo złożone obiekty.
podwójnie
Test1 zajął: 2710 ms
Test2 zajął: 2790 ms
Ciąg (po prostu zamień podwójnie na ciąg w testach)
Test3 zajął: 1200 ms
Test4 zajął: 3000 ms
Kompilowanie i pobieranie kodu bajtowego
ZAKTUALIZOWANA ODPOWIEDŹ
Naprawdę nie jest łatwo porównać wydajność ze wszystkimi optymalizacjami JVM. Jest to jednak w pewnym stopniu możliwe. Lepszy test i szczegółowe wyniki w Google Caliper
Częściowy kod testu dla podwójnej deklaracji
Nie jest to identyczne z powyższym kodem. Jeśli po prostu kodujesz sztuczną pętlę, JVM pomija ją, więc przynajmniej musisz coś przypisać i zwrócić. Jest to również zalecane w dokumentacji Calipera.
źródło
Jednym z rozwiązań tego problemu może być zapewnienie zmiennego zakresu enkapsulującego pętlę while:
Zostaną one automatycznie usunięte z odniesienia po zakończeniu zakresu zewnętrznego.
źródło
Wewnątrz, im mniejszy zakres, zmienna jest widoczna, tym lepiej.
źródło
Jeśli nie musisz używać
str
pętli while (związanej z zakresem), to drugi warunek, tjjest lepszy, ponieważ jeśli zdefiniujesz obiekt na stosie, tylko jeśli
condition
jest to prawda. Używam go, jeśli go potrzebujeszźródło
Myślę, że najlepszym źródłem odpowiedzi na twoje pytanie będzie następujący post:
Różnica między deklarowaniem zmiennych przed lub w pętli?
Według mojego zrozumienia, ta rzecz byłaby zależna od języka. IIRC Java optymalizuje to, więc nie ma żadnej różnicy, ale JavaScript (na przykład) zajmie się przydzielaniem całej pamięci za każdym razem w pętli. W Javie szczególnie myślę, że drugi działałby szybciej po zakończeniu profilowania.
źródło
Jak zauważyło wiele osób,
NIE jest lepsze niż to:
Więc nie deklaruj zmiennych poza ich zasięgiem, jeśli nie używasz ich ponownie ...
źródło
Zadeklarowanie ciągu stru na zewnątrz pętli wile umożliwia odwołanie do niej wewnątrz i na zewnątrz pętli while. Deklaracja ciągu str w pętli while pozwala na odwołanie się do niej tylko w pętli while.
źródło
Zmienne powinny być deklarowane tak blisko miejsca, w którym są używane, jak to możliwe.
Ułatwia to RAII (Resource Acquisition Is Initialization) .
Utrzymuje wąski zakres zmiennej. Dzięki temu optymalizator działa lepiej.
źródło
Według Przewodnika programistycznego Google Android zakres zmiennych powinien być ograniczony. Sprawdź ten link:
Ogranicz zakres zmienny
źródło
str
Zmienna będzie dostępna i zastrzeżone trochę miejsca w pamięci nawet po chwili wykonywany poniżej kodu.str
Zmienna nie będzie dostępna, a także pamięć zostanie zwolniony, który został przydzielony dostr
zmiennej w poniżej kodu.Jeśli zastosujemy się do drugiego, z pewnością zmniejszy to pamięć systemową i zwiększy wydajność.
źródło
Zadeklarowanie wewnątrz pętli ogranicza zakres odpowiedniej zmiennej. Wszystko zależy od wymagań projektu dotyczących zakresu zmiennej.
źródło
Naprawdę, powyższe pytanie jest kwestią programistyczną. Jak chcesz zaprogramować swój kod? Gdzie potrzebujesz dostępu do „STR”? Nie ma sensu deklarować zmiennej, która jest używana lokalnie jako zmienna globalna. Podstawy programowania wierzę.
źródło
Te dwa przykłady skutkują tym samym. Jednak pierwszy zapewnia użycie
str
zmiennej poza pętlą while; drugi nie jest.źródło
Ostrzeżenie dla prawie wszystkich osób w tym pytaniu: Oto przykładowy kod, w którym wewnątrz pętli może być 200 razy wolniejszy na moim komputerze z Javą 7 (a zużycie pamięci jest również nieco inne). Ale dotyczy alokacji, a nie tylko zakresu.
Wniosek: w zależności od wielkości zmiennej lokalnej różnica może być ogromna, nawet przy niezbyt dużych zmiennych.
Wystarczy powiedzieć, że czasami na zewnątrz lub wewnątrz pętli ma znaczenie.
źródło
bigStuff[(int) (value % STUFF_SIZE)] = value;
(Wypróbuj wartość 2147483649L)Myślę, że rozmiar obiektu również ma znaczenie. W jednym z moich projektów zadeklarowaliśmy i zainicjowaliśmy dużą dwuwymiarową tablicę, która powodowała, że aplikacja generowała wyjątek braku pamięci. Zamiast tego usunęliśmy deklarację z pętli i wyczyściliśmy tablicę na początku każdej iteracji.
źródło
Istnieje ryzyko,
NullPointerException
żecalculateStr()
metoda zwróci null, a następnie spróbujesz wywołać metodę na str.Mówiąc bardziej ogólnie, unikaj posiadania zmiennych o wartości zerowej . Nawiasem mówiąc, jest silniejszy dla atrybutów klasy.
źródło
NullPointerException.
że próba wykonania tego kodureturn str;
napotka błąd kompilacji.