Статические члены класса

Разные экземпляры одного класса имеют совершенно независимые друг от друга поля-, принимающие разные значения. Изменение поля в одном экземпляре никак не влияет на то же поле в другом экземпляре. В каждом экземпляре для таких полей выделяется своя ячейка памяти. Поэтому такие поля называются переменными экземпляра класса (instance variables) или переменными объекта.

Иногда надо определить поле, общее для всего класса, изменение которого в одном экземпляре повлечет изменение того же поля во всех экземплярах. Например, мы хотим в классе Automobile отмечать порядковый заводской номер автомобиля. Такие поля называются переменными класса (class variables). Для переменных класса выделяется только одна ячейка памяти, общая для всех экземпляров. Переменные класса образуются в Java модификатором static. В листинге 2.3 мы записываем этот модификатор при определении переменной number.

Листинг 2.3. Статическая переменная

class Automobile {

   private static int number; 

   Automobile(){ 

      number++;

      System.out.println("From Automobile constructor:"+ 

                         " number = "+number);

   }

}

public class AutomobiieTest{

   public static void main(String[] args){

   Automobile lada2105    = new Automobile(), 

              fordScorpio = new Automobile(),

              oka         = new Automobile!);

   } 

}

Получаем результат, показанный на рис. 2.2.

Рис. 2.2. Изменение  статической переменной

Интересно, что к статическим переменным можно обращаться с именем класса, Automobile.number, а не только с именем экземпляра, lada2105.number, причем это можно делать, даже если не создан ни один экземпляр класса.

Для работы с такими статическими переменными обычно создаются статические методы, помеченные модификатором static. Для методов слово static имеет совсем другой смысл. Исполняющая система Java всегда создает в памяти только одну копию машинного кода метода, разделяемую всеми экземплярами, независимо от того, статический это метод или нет.

Основная особенность статических методов — они выполняются сразу во всех экземплярах класса. Более того, они могут выполняться, даже если не создан ни один экземпляр класса. Достаточно уточнить имя метода именем класса (а не именем объекта), чтобы метод мог работать. Именно так мы пользовались методами класса Math, не создавая его экземпляры, а просто записывая Math.abs(x), Math.sqrt(x). Точно так же мы использовали метод System, out. println(). Да и методом main() мы пользуемся, вообще не создавая никаких объектов.

Поэтому статические методы называются методами класса (class methods), в отличие от нестатических методов, называемых методами экземпляра (instance methods).

Отсюда вытекают другие особенности статических методов:

Именно поэтому в листинге 1.5 мы пометили метод f() модификатором static. Но в листинге 2.1 мы работали с экземпляром b2 класса Bisection2, и нам не потребовалось объявлять метод f() статическим.

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

static int[] a = new a[10]; 

static {

for(int k = 0; k < a.length; k++) 

a[k] = k * k; 

}

Операторы, заключенные в такой блок, выполняются только один раз, при первой загрузке класса, а не при создании каждого экземпляра.

Здесь внимательный читатель, наверное, поймал меня: "А говорил, что все действия выполняются только с помощью методов!" Каюсь: блоки статической инициализации, и блоки инициализации экземпляра записываются вне всяких методов и выполняются до начала выполнения не то что метода, но даже конструктора.

 

Сайт создан в системе uCoz