Почему локальные переменные, включая примитивы, всегда должны инициализироваться в Java? - PullRequest
50 голосов
/ 13 октября 2009

Почему локальные переменные, включая примитивы, всегда должны инициализироваться в Java? Почему то же самое не применимо в случае переменных экземпляра?

Ответы [ 8 ]

62 голосов
/ 13 октября 2009

Совсем недавно был задан вопрос об этом для C # ... - также прочитайте ответы там, поскольку это в основном то же самое. Вы также можете найти недавнее сообщение в блоге Эрика Липперта интересным; он, по крайней мере, примерно в одной области, хотя у него несколько иная тяга.

По сути, требование, чтобы переменной было присвоено значение до того, как вы ее прочитаете, - хорошая вещь. Это означает, что вы случайно не прочитаете то, что не собирались делать. Да, переменные могут иметь значения по умолчанию - но разве не лучше, чтобы компилятор мог вместо этого перехватить вашу ошибку, если он может доказать, что вы пытаетесь прочитать что-то, что, возможно, еще не было назначено? Если вы хотите присвоить локальной переменной значение по умолчанию, вы всегда можете назначить это явно.

Теперь это хорошо для локальных переменных - но, например, для статических переменных, компилятор не может знать, в каком порядке будут вызываться методы. Будет ли свойство "setter" вызываться перед "getter"? У него нет возможности узнать, поэтому он не может предупредить вас об опасности. Вот почему значения по умолчанию используются для экземпляров / статических переменных - по крайней мере, тогда вы получите известное значение (0, false, null и т. Д.) Вместо просто «того, что было в памяти в то время. " (Это также устраняет потенциальную проблему безопасности чтения конфиденциальных данных, которые не были явно стерты.)

8 голосов
/ 14 января 2012

В Java переменные класса и экземпляра принимают значение по умолчанию (null, 0, false), если они не инициализированы вручную. Однако локальные переменные не имеют значения по умолчанию. Если локальной переменной не присвоено значение, компилятор откажется компилировать код, который ее читает. ИМХО, это приводит к выводу, что инициализация локальной переменной с некоторым значением по умолчанию (например, null, которое может привести к NullPointerException позже), когда она объявлена, на самом деле плохая вещь. Рассмотрим следующий пример:

Object o;
if (<some boolean condition>)
  o = <some value>;
else
  o = <some other value>;
System.out.println(o);

Инициализация o с нулевым значением совершенно не требуется, поскольку компилятор Java проверяет во время компиляции, что любой путь кода инициализирует o (с нулевым или некоторым ненулевым значением) перед чтением переменной. Это означает, что компилятор откажется компилировать строку System.out.println(o);, если вы закомментируете любую из двух инициализаций переменной o в приведенном выше фрагменте кода.

Это относится к Java и, возможно, только к Java. Я не знаю о языке, как C #. В старом добром C (и, возможно, C ++) все же рекомендуется всегда инициализировать переменные при объявлении их, AFAIK. Такие "старые школы" языки программирования могут быть причиной того, что рекомендация всегда инициализировать переменные появляется в книгах и дискуссиях о современных языках, таких как Java, где компилятор отслеживает, была ли переменная инициализирована или нет.

8 голосов
/ 13 октября 2009

Что ж, в случае локальной переменной ясно, что она означает «до», поскольку поток программы между объявлением (в методе) и ссылкой является последовательным. В случае, когда поля, объявленные вне метода, компилятор никогда не знает, какой код будет использоваться, когда он не может сгенерировать ошибку, поскольку, возможно, какой-то другой метод будет инициализировать поле перед его использованием.

6 голосов
/ 13 октября 2009

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

int x;  // Valid
int y;
println("y=" + y);  // Not valid since y's value has never been assigned
1 голос
/ 13 октября 2009

Локальные переменные и примитивы должны быть инициализированы перед использованием, потому что вы знаете, чего ожидать от значений. Исторически, когда создавалась новая переменная, она содержала случайные значения из памяти [и никто не мог предсказать значение]. Java также требует этого, потому что это предотвращает присутствие потерянных переменных.

0 голосов
/ 08 декабря 2018

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

0 голосов
/ 03 июня 2018

Необходимо инициализировать локальные переменные (только когда мы их используем), потому что они не получают никаких значений по умолчанию, таких как переменные экземпляра.

И, как правило, мы всегда должны инициализировать любую переменную перед ее использованием. В противном случае это может привести к ошибке, такой как nullPointer и т. Д.

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

Поэтому, когда стек завершится, значение локального метода также будет уничтожено, поэтому: 1] Они должны быть инициализированы явно (когда мы их используем) 2] Они не должны инициализироваться неявно (нулем, 0 или ложью), как переменные экземпляра

0 голосов
/ 13 октября 2009

На практике все переменные необходимо инициализировать перед их использованием.

Я не могу вспомнить время, когда вы захотите использовать переменную, прежде чем устанавливать ее значение (если вы не сравниваете ее с нулем).

...