В дополнение к тому факту, что поля static
принадлежат их классам, и, таким образом, существует только один экземпляр static
varaible на класс (и на загрузчик классов), важно понимать, что static final
переменные, инициализированные компиляцией постоянные выражения встроены в классы, которые их используют .
JLS §13.1 Форма двоичного файла :
Ссылки на поля, которые являются постоянными переменными (§4.12.4), разрешаются во время компиляции в постоянное значение, которое обозначается. Никакая ссылка на такое постоянное поле не должна присутствовать в коде в двоичном файле (за исключением класса или интерфейса, содержащего постоянное поле, в котором будет код для его инициализации), и такие постоянные поля должны всегда казаться инициализированными; начальное значение по умолчанию для типа такого поля никогда не должно соблюдаться.
Таким образом, на практике экземпляр переменной static final
, принадлежащий ее классу, не является единственным экземпляром значения этой переменной - существуют другие экземпляры этого значения, встроенные в пулы констант (или код) классов, которые используют рассматриваемая переменная.
class Foo {
public static final String S = "Hello, world!";
}
class Bar {
public static void main(String[] args) {
// No real access to class Foo here
// String "Hello, world!" is inlined into the constant pool of class Bar
String s = Foo.S;
System.out.println(s);
}
}
На практике это означает, что если вы измените значение Foo.S
в классе Foo
, но не перекомпилируете класс Bar
, класс Bar
выведет старое значение Foo.S
.