2012-01-31 12 views
24

Dokumentacja języka Java mówi: "Jeśli typ pierwotny lub łańcuch jest zdefiniowany jako stała, a wartość jest znana w czasie kompilacji, kompilator zastępuje stałą nazwę wszędzie w kodzie jej wartością. jest nazywana stałą czasu kompilacji. "Stałe i zmienne czasowe kompilacji

Więc moje rozumienie jest jeśli mamy kawałek kodu:

private final int x = 10; 

Następnie kompilator zastąpi każde wystąpienie „x” w kodzie z dosłownym „10”. Ale powiedzmy Załóżmy, że stała jest inicjowany z wartością w czasie wykonywania,

private final int x = getX(); // here getX() returns an integer value at run-time. 

Czy będzie żadnego spadku wydajności (jakkolwiek nieistotny) może być porównana do kompilacji stałą?

Inną kwestią jest to, czy poniższy wiersz kodu:

private int y = 10; // here y is not final 

jest traktowany w taki sam sposób jak kompilacji stałą przez kompilator?

EDIT: Wreszcie, co rozumiem z odpowiedzi to:

  1. final static środki kompilacji stałą
  2. tylko final oznacza jego stałą ale jest inicjowany w czasie wykonywania
  3. tylko static oznacza zainicjalizowany w czasie wykonywania
  4. bez final jest zmienną i nie będzie traktowany jako stały.

Czy moje zrozumienie jest prawidłowe?

+5

o punkcie 2. Mylisz się! końcowy int a = 1; a jest stałą czasu kompilacji. końcowy int b; b = 1; b nie jest – landry

Odpowiedz

41

kompilacji Stała czasowa musi być:

  • ogłosił ostateczny
  • prymitywny lub String
  • zainicjowany w ciągu deklaracji
  • inicjowane ze stałą ekspresję

Więc private final int x = getX(); nie jest stała .

Na drugie pytanie private int y = 10; nie jest stała (w tym przypadku nie jest ostateczna), więc optymalizator nie może być pewien, że wartość nie zmieni się w przyszłości. Więc nie może zoptymalizować go tak dobrze jak stała wartość. Odpowiedź brzmi: Nie, nie jest traktowana w taki sam sposób, jak stała czasowa kompilacji.

+2

JLS definiująca stałą ekspresję: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 –

+1

jeszcze jeden przykład, aby usunąć wątpliwości: finał int a = 1; jest stałą czasową kompilacji, ale końcową int a; a = 2; nie jest –

+0

myślę, że można go zainicjować wewnątrz deklaracji lub w ramach constuctor –

1

Nie może być naprawdę niewielki spadek wydajność na niektóre maszyny do private final int x = getX(); Od tego wymagałoby co najmniej jedno połączenie metody (oprócz faktu, że nie jest to czas kompilacji stała), ale jak ty powiedział, że byłoby to zaniedbywanie, więc po co zawracać sobie głowę?

Co do drugiego pytania: y nie jest ostateczny, a zatem nie jest stałą czasową kompilacji, ponieważ może zmienić się w czasie wykonywania.

1

private final int x = getX(); Zostanie wywołany przy pierwszym zadeklarowaniu obiektu. Spadek wydajności będzie zależeć od getX(), ale to nie jest rodzaj rzeczy, aby stworzyć wąskie gardło.

2

Parametr final oznacza, że ​​zmienna zostanie zainicjowana tylko jeden raz. Prawdziwa stała potrzeba również zostać zadeklarowana jako static. Tak więc żaden z twoich przykładów nie jest traktowany przez kompilator jako stałe. Niemniej jednak, ostatnie słowo kluczowe informuje (i kompilator), że zmienne będą inicjowane tylko raz (w konstruktorze lub dosłownie). Jeśli potrzebujesz ich wartości przypisanych podczas kompilacji, twoje pola muszą być statyczne.

Wydajność tak naprawdę nie ma na to wpływu, ale należy pamiętać, że typy pierwotne są niezmienne, gdy już je utworzysz, utrzyma je w pamięci, aż śmieciarz je usunie. Tak więc, jeśli masz zmienną y = 1;, a następnie zmienisz ją na y = 2; w pamięci, JVM będzie miała obie wartości, ale twoja zmienna "wskaże" to drugie.

int prywatna wartość = 10; // tutaj nie jest ostateczny

jest traktowany tak samo jak kompilacja stała czasowa przez kompilator?

Nie. Jest to zmienna instancji, utworzona, zainicjowana i użyta w środowisku wykonawczym.

0

Według JLS nie ma wymogu, aby "stała zmienna" była statyczna.

"Zmienna stała" może być statyczna lub niestatyczna (zmienna instancji).

Ale JLS nakłada jakieś inne wymagania dla zmiennej być „zmienna stała” (oprócz tego, że tylko wersja ostateczna):

  • jest tylko String lub prymitywne
  • zainicjowane inline tylko, dlatego, że jest ostateczna, i pusty końcowy nie może
  • inicjowany „stałej ekspresji” = „w czasie kompilacji” stałej ekspresji (patrz poniżej) JLS cytat

4.12.4. final Variables (JLS)

A stałej zmiennej jest końcowym zmienną pierwotnej typu lub typu ciąg znaków, który jest inicjowany przy stałej ekspresji (§15.28).

15.28. Constant Expressions

kompilacji stałym wyrażeniem jest wyrazem oznaczającym wartość prymitywnego typu lub ciąg znaków, który nie kończy się nagle i jest składa się przy użyciu wyłącznie:

Literały o typie pierwotnym i literałach typu String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)

Odlewane do typów pierwotnych i rzutów do typu String (§15.16)

Operatory jednoargumentowe +, -, ~ i! (Ale nie ++ lub -) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)

Operatorzy multiplikatywne *,/i% (§15.17)

operatorzy dodatków + i - (§15.18)

operatory przesunięcia < <, >> i >>> (§15.19)

operatorzy relacyjne <, < =,> i> = (ale nie instanceof) (§15.20)

Operatory równości == i! = (§15.21)

Operatory bitowe i logiczne &,^i | (§15.22)

Operator warunkowy i operator & & i operator warunkowy lub || (§15.23, §15.24)

Trójskładnikowy operator warunkowy? : (§ 15.25)

Wyrazy o nawiasach (§15.8.5), których zawartym wyrażeniem jest wyrażenie stałe o stałej długości .

Nazwy proste (§6.5.6.1), które odnoszą się do zmiennych stałych (§4.12.4).

Nazwy kwalifikowane (§6.5.6.2) formularza NazwaPseudonimu. Identyfikator, który odnosi się do zmiennych stałych (§4.12.4).