Есть ли разница когда инициализировать значение переменной?

Рейтинг: 4Ответов: 3Опубликовано: 18.03.2023

Пока не очень силен в синтаксисе java. Нашел вот такой пример:

private static int CARS_COUNT;

static {

    CARS_COUNT = 0;
}

Есть ли существенное различие, если я напишу так?:

private static int CARS_COUNT = 0;

В плане возможностей работы с данной переменной

Ответы

▲ 5

Пожалуй, следует дополнить предыдущий ответ.

Следует понимать, что сами по себе static-поля хранятся в специальном месте кучи (heap) памяти java. Там есть своеобразный пул значений, которые могут часто использоваться (как раз таки одно из назначений статик поля - задание констант). Поэтому эти значения загружаются в это место в памяти самыми первыми.

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

Так как в нашем случае поле int ( а это примитивный тип данных), то и в память загрузится 0. После этого в память загрузится U, в которую присвоено значение 0. И только после этого выполнится статический инициализатор и I получит значение равное 5. Если поменять местами так, то выведется значение равное 5:

public class MyClass {

    static int I;

    static {
        I = 5;
    }
    
    //static блок ещё не выполнился поэтому I=0;
    static int U = I;

    public static void main(String args[]) {
        System.out.println("U = " + U); // выведет 5
    }
}

Что касаемо исходного примера, то разницы не будет, если то static-инициализатора это поле не использовалось. Успехов!

▲ 4

Разница есть. В первом варианте до выполнения static блока переменная будет иметь значение по умолчанию. Если её использовать до выполнения static блока - будет использовано значение по умолчанию.

public class MyClass {

    static int I;
    
    //static блок ещё не выполнился поэтому I=0;
    static int U = I;
    
    static {
        I = 5;
    }
    
    //а вот тут уже static блок выполнился и U будет равно 5
    // static int U = I;

    public static void main(String args[]) {
        System.out.println("U = " + U); // выведет 0
    }
}
▲ 2

Немного про примитивы и значение по умолчанию

Тип int - примитивный тип данных. Переменная этого типа не ссылается на какой-то класс, а просто хранит в себе какое-либо значение. И когда вы не даёте никакого значения примитиву, то ему присваивается значение по умолчанию (для типа int это 0).

То эта запись

private static int CARS_COUNT;

даст тот же результат, что и эта:

private static int CARS_COUNT = 0; 

А теперь разберём ваш пример

private static int CARS_COUNT; //Переменная имеет значение по умолчанию, т.е 0

static {

    CARS_COUNT = 0; //Вы присваиваете переменной то же самое значение, какое у неё и было
}

В данном случае статический инициализатор ничего не меняет. Но вы могли сделать так, как уже говорил @ЮрийСПб♦. Вы же могли в статическом инициализаторе присвоить переменной другое значение (не ноль):

 static {
      CARS_COUNT = 11;  
 }

тогда бы переменная имела бы значение 11, а не 0.

Но если статической переменной можно сразу дать нужное значение, то зачем конструкция static{}?

Представьте, что у вас не статическая переменная типа int, а статический массив. Да, вы конечно можете сделать так:

static int[] array = new int[]{1, 2, 3, 4, 5, 6, 7};

Но если вам нужно заполнить массив не заранее известными числами, а числами, которые возвращают какие-то методы? А если в массиве 100 элементов и их надо заполнить циклом? В таком случае вам поможет статический инициализатор. Вот пример:

int[] array = new int[100];
 
static{
    int j = 0;
    for(int i = 0; i < array.length; i++){
         j++;
         array[i] = j;
    }
}

Можно посмотреть ответ на этот вопрос, если хотите узнать больше о конструкции static{}