Musimy rozróżnić dwa aspekty stałych:
- nazwy wartości znanych w czasie opracowywania, które wprowadzamy dla lepszej konserwacji, oraz
- wartości dostępne dla kompilatora.
A potem jest pokrewny trzeci rodzaj: zmienne, których wartość się nie zmienia, tj. Nazwy wartości. Różnica między tymi niezmiennymi zmiennymi a stałą polega na tym, że wartość jest określana / przypisywana / inicjalizowana: zmienna jest inicjalizowana w czasie wykonywania, ale wartość stałej jest znana podczas programowania. To rozróżnienie jest nieco mętne, ponieważ wartość może być znana podczas programowania, ale w rzeczywistości jest tworzona tylko podczas inicjalizacji.
Ale jeśli wartość stałej jest znana w czasie kompilacji, to kompilator może wykonywać obliczenia z tą wartością. Na przykład język Java ma pojęcie wyrażeń stałych . Stałe wyrażenie to dowolne wyrażenie, które składa się tylko z literałów pierwotnych lub łańcuchów, operacji na stałych wyrażeniach (takich jak rzutowanie, dodawanie, łączenie łańcuchów) i zmiennych stałych. [ JLS § 15.28 ] Zmienna stała jest final
zmienną, która jest inicjowana stałym wyrażeniem. [JLS §4.12.4] Tak więc dla Javy jest to stała czasowa kompilacji:
public static final int X = 7;
Staje się to interesujące, gdy zmienna stała jest używana w wielu jednostkach kompilacji, a następnie deklaracja jest zmieniana. Rozważać:
Teraz, kiedy kompilujemy te pliki, B.class
kod bajtowy zadeklaruje pole, Y = 9
ponieważ B.Y
jest zmienną stałą.
Ale kiedy zmienimy A.X
zmienną na inną wartość (powiedzmy X = 0
) i ponownie skompilujemy tylko A.java
plik, wówczas B.Y
nadal będzie się odnosić do starej wartości. Ten stan A.X = 0, B.Y = 9
jest niezgodny z deklaracjami w kodzie źródłowym. Miłego debugowania!
Nie oznacza to, że stałe nigdy nie powinny być zmieniane. Stałe są zdecydowanie lepsze niż magiczne liczby, które pojawiają się bez wyjaśnienia w kodzie źródłowym. Jednak wartość stałych publicznych jest częścią publicznych API . Nie jest to specyficzne dla Javy, ale występuje również w C ++ i innych językach, które zawierają osobne jednostki kompilacji. Jeśli zmienisz te wartości, będziesz musiał ponownie skompilować cały zależny kod, tj. Wykonać czystą kompilację.
W zależności od charakteru stałych mogły one prowadzić do błędnych założeń programistów. Jeśli te wartości zostaną zmienione, mogą spowodować błąd. Na przykład można wybrać zestaw stałych, aby tworzyły pewne wzorce bitowe, np public static final int R = 4, W = 2, X = 1
. Jeśli zostaną one zmienione w celu utworzenia innej struktury, takiej jak R = 0, W = 1, X = 2
istniejący kod, taki jak, stanie boolean canRead = perms & R
się niepoprawny. Pomyśl tylko o zabawie, która Integer.MAX_VALUE
się zmieni! Nie ma tutaj poprawki, należy tylko pamiętać, że wartość niektórych stałych jest naprawdę ważna i nie można jej po prostu zmienić.
Ale dla większości stałych zmiana ich będzie w porządku, o ile uwzględnione zostaną powyższe ograniczenia. Stałą można bezpiecznie zmienić, gdy znaczenie, a nie konkretna wartość, jest ważne. Dzieje się tak np. W przypadku tunerów takich jak BORDER_WIDTH = 2
lub TIMEOUT = 60; // seconds
lub szablonów takich jak API_ENDPOINT = "https://api.example.com/v2/"
- choć prawdopodobnie niektóre lub wszystkie z nich powinny być określone w plikach konfiguracyjnych, a nie w kodzie.