Есть ли разница когда инициализировать значение переменной?
Пока не очень силен в синтаксисе java. Нашел вот такой пример:
private static int CARS_COUNT;
static {
CARS_COUNT = 0;
}
Есть ли существенное различие, если я напишу так?:
private static int CARS_COUNT = 0;
В плане возможностей работы с данной переменной
Ответы (3 шт):
Разница есть. В первом варианте до выполнения 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
}
}
Пожалуй, следует дополнить предыдущий ответ.
Следует понимать, что сами по себе 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-инициализатора это поле не использовалось. Успехов!
Немного про примитивы и значение по умолчанию
Тип 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{}