Философия Java

Инициализация статических данных


Когда данные являются статическими, происходит то же самое; если это примитивные типы и вы не инициализируете их, они получают стандартное начальное значение примитивных типов. Если это ссылка на объект, она становится равной null, если вы не создадите новый объект и не присоедините его к этой ссылке.

Если вы хотите поместить инициализацию в точку определения, это выглядит точно так же, как и для не статических членов. Есть единственный кусочек хранилища для static, не зависимо от того, сколько объектов создано. Но вопрос о том, когда инициализируется static хранилище, остается. Этот пример снимает этот вопрос:

//: c04:StaticInitialization.java

// Указание начальных значений в

// определении класса.

class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f(int marker) { System.out.println("f(" + marker + ")"); } }

class Table { static Bowl b1 = new Bowl(1); Table() { System.out.println("Table()"); b2.f(1); } void f2(int marker) { System.out.println("f2(" + marker + ")"); } static Bowl b2 = new Bowl(2); }

class Cupboard { Bowl b3 = new Bowl(3); static Bowl b4 = new Bowl(4); Cupboard() { System.out.println("Cupboard()"); b4.f(2); } void f3(int marker) { System.out.println("f3(" + marker + ")"); } static Bowl b5 = new Bowl(5); }

public class StaticInitialization { public static void main(String[] args) { System.out.println( "Creating new Cupboard() in main"); new Cupboard(); System.out.println( "Creating new Cupboard() in main"); new Cupboard(); t2.f2(1); t3.f3(1); } static Table t2 = new Table(); static Cupboard t3 = new Cupboard(); } ///:~

Bowl позволяет вам наблюдать за созданием класса, а Table и Cupboard создают static-члены Bowl вперемешку в определении класса. Обратите внимание, что Cupboard создает не-static Bowl b3 перед static определением. На выводе вы видите, что произошло:

Bowl(1) Bowl(2) Table() f(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) Creating new Cupboard() in main Bowl(3) Cupboard() f(2) f2(1) f3(1)


Static инициализация происходит только при необходимости. Если вы не создаете объект Table и никогда не обращаетесь к Table.b1 или Table.b2, static Bowl b1 и b2 никогда не будут созданы. Однако они инициализируются, только когда создается первый объект Table (или при возникновении первого static доступа static). После этого static объекты не инициализируются повторно.

Порядок инициализации таков: сначала инициализируются static, если они ранее не были инициализированы при создании предыдущего объекта, а затем инициализируются не static объекты. Вы ясно можете видеть в результатах работы программы.

Полезно просуммировать информацию о процессе создания объекта. Рассмотрим класс с названием Dog:

  • В начале создания объекта типа Dog, или при первом обращении к static методу или static полу класса Dog, интерпретатор Java должен найти Dog.class, что он выполняет, производя поиск по classpath.


  • После загрузки Dog.class (создания объекта Class, о котором вы узнаете позже), выполняются все static инициализации. Таким образом, static инициализации выполняются только однажды, когда объект Class загружается в первое время.
  • Когда вы создаете new Dog( ), в процессе создания объекта Dog сначала резервируется хранилище для объекта Dog в куче.


  • Это хранилище заполняется нулями, автоматически присваивая всем переменным примитивных типов этого объекта Dog их начальное значение (ноль для числовых и эквивалент для boolean и char), а все ссылки в null.


  • Выполняются все инициализации, производящиеся в точке определения.


  • Выполняется конструктор. Как вы увидите в Главе 6, это может стать источником повышенной активности, особенно когда привлекается наследование.



  • Содержание раздела