Po pierwsze, układanka: co drukuje następujący kod?
public class RecursiveStatic {
public static void main(String[] args) {
System.out.println(scale(5));
}
private static final long X = scale(10);
private static long scale(long value) {
return X * value;
}
}
Odpowiedź:
0
Spojlery poniżej.
Jeśli drukujesz X
w skali (długiej) i redefiniujesz X = scale(10) + 3
, wydruki będą X = 0
wtedy X = 3
. Oznacza to, że X
jest tymczasowo ustawiony na, 0
a później ustawiony na 3
. To jest naruszenie final
!
Modyfikator statyczny w połączeniu z modyfikatorem końcowym służy również do definiowania stałych. Ostatni modyfikator wskazuje, że wartość tego pola nie może się zmienić .
Źródło: https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html [podkreślenie dodane]
Moje pytanie: czy to błąd? Jest final
źle zdefiniowany?
Oto kod, który mnie interesuje.
X
Przypisano mu dwie różne wartości: 0
i 3
. Uważam, że jest to naruszenie final
.
public class RecursiveStatic {
public static void main(String[] args) {
System.out.println(scale(5));
}
private static final long X = scale(10) + 3;
private static long scale(long value) {
System.out.println("X = " + X);
return X * value;
}
}
To pytanie zostało oznaczone jako możliwy duplikat statycznej kolejności inicjalizacji pola końcowego Java . Uważam, że to pytanie nie jest duplikatem, ponieważ drugie pytanie dotyczy kolejności inicjalizacji, podczas gdy moje pytanie dotyczy cyklicznej inicjalizacji połączonej ze final
znacznikiem. Na podstawie samego drugiego pytania nie byłbym w stanie zrozumieć, dlaczego kod w moim pytaniu nie powoduje błędu.
Jest to szczególnie wyraźne, patrząc na wyniki, które otrzymuje Ernest: gdy a
jest oznaczony final
, otrzymuje następujące dane wyjściowe:
a=5
a=5
co nie obejmuje głównej części mojego pytania: w jaki sposób final
zmienna zmienia swoją zmienną?
A blank final instance variable must be definitely assigned (§16.9) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs.
X
członka jest jak odwoływanie się do członka podklasy przed zakończeniem konstruktora superklasy, to twój problem, a nie definicjafinal
.