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

Хотя у меня нет сложного сравнения, как большинство из этих ответов, я хотел бы поделиться своим методом для обработки этой ситуации. Расширяя IEnumerable<T>, вы можете позволить вашему классу Team поддерживать расширения запросов Linq, не публично раскрывая все методы и свойства List<T>.

class Team : IEnumerable<Player>
{
    private readonly List<Player> playerList;

    public Team()
    {
        playerList = new List<Player>();
    }

    public Enumerator GetEnumerator()
    {
        return playerList.GetEnumerator();
    }

    ...
}

class Player
{
    ...
}
95
задан Gaurav Jeswani 22 June 2016 в 06:04
поделиться

9 ответов

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

57
ответ дан allprog 24 November 2019 в 05:53
поделиться

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

0
ответ дан David Santamaria 24 November 2019 в 05:53
поделиться

Eclipse даже дает Вам предупреждения неинициализированных переменных, таким образом, это становится довольно очевидным так или иначе. Лично я думаю, что это - хорошая вещь, что это - поведение по умолчанию, иначе Ваше приложение может использовать неожиданные значения, и вместо компилятора, бросающего ошибку, это ничего не сделает (но возможно даст предупреждение), и затем Вы будете царапать голову относительно того, почему определенные вещи не вполне ведут себя способ, которым они должны.

0
ответ дан Kezzer 24 November 2019 в 05:53
поделиться

Я думаю, что основная цель должна была поддержать подобие с C/C++. Однако компилятор обнаруживает и предупреждает Вас об использовании неинициализированных переменных, которые уменьшат проблему до минимальной точки. С точки зрения производительности это немного быстрее, чтобы позволить Вам объявить неинициализированные переменные, так как компилятор не должен будет писать оператор присваивания даже при перезаписи значения переменной в следующем операторе.

4
ответ дан Mehrdad Afshari 24 November 2019 в 05:53
поделиться

Кроме того, в примере ниже, исключение, возможно, было выдано в конструкции SomeObject, в этом случае, 'таким образом' переменная была бы пустой, и вызов к CleanUp бросит NullPointerException

SomeObject so;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  so.CleanUp(); // Compiler error here
}

, Что я склонен делать, это:

SomeObject so = null;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  if (so != null) {
     so.CleanUp(); // safe
  }
}
12
ответ дан Electric Monk 24 November 2019 в 05:53
поделиться

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

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

10
ответ дан Adeel Ansari 24 November 2019 в 05:53
поделиться

"проблема" Вы связываетесь с [1 124], кажется, описывает эту ситуацию:

SomeObject so;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  so.CleanUp(); // Compiler error here
}

жалоба комментатора - то, что компилятор передумал относительно строки в эти finally раздел, утверждая, что so могло бы быть неинициализированным. Комментарий тогда упоминает другой способ записать код, вероятно, что-то вроде этого:

// Do some work here ...
SomeObject so = new SomeObject();
try {
  so.DoUsefulThings();
} finally {
  so.CleanUp();
}

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

Так или иначе, эта вторая версия кода корректна способ записать его. В первой версии сообщение об ошибке компилятора было корректно. so переменная могла бы быть неинициализированной. В частности, если SomeObject сбои конструктора, so не будут инициализированы, и таким образом, это будет ошибка попытаться звонить so.CleanUp. Всегда входите try раздел после , Вы получили ресурс, который эти finally завершает раздел.

try - finally блок после so инициализация там [только 1 127], чтобы защитить SomeObject экземпляр, удостовериться, что это очищено, неважно, что еще происходит. Если существует другой вещи, которые должны работать, но они не связаны с тем, был ли SomeObject экземпляр выделенным свойством, то они должны войти другой try - finally блок, вероятно, тот, который обертывает тот, который я показал.

переменные Требования, которые будут присвоены вручную, прежде чем использование не приводит к настоящим проблемам. Это только приводит к незначительным стычкам, но Ваш код будет лучше для него. У Вас будут переменные с более ограниченным объемом, и try - finally блоки, которые не пытаются защитить слишком много.

, Если локальные переменные имели значения по умолчанию, то so в первом примере будет null. Это ничего действительно не решило бы. Вместо того, чтобы получить ошибку времени компиляции в finally блок, Вы имели бы NullPointerException потаенный там, который мог бы скрываться независимо от того, что другое исключение могло произойти в разделе "Do some work here" кода. (Или исключения в [1 123] разделы, автоматически цепочечные к предыдущему исключению? Я не помню. Несмотря на это, у Вас было бы дополнительное исключение в способе реального.)

23
ответ дан Rob Kennedy 24 November 2019 в 05:53
поделиться

Более эффективно не инициализировать переменные, и в случае локальных переменных безопасно сделать так, потому что инициализация может быть прослежена компилятором.

В случаях, где Вам нужна переменная, которая будет инициализирована, можно всегда делать это сами, таким образом, это не проблема.

3
ответ дан starblue 24 November 2019 в 05:53
поделиться

(Может показаться странным публиковать новый ответ так долго после вопроса, но появился дубликат .)

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

Тем не менее, я мог полностью отказаться от требования, чтобы переменные экземпляра всегда явно инициализировались; ошибка может возникнуть в любом конструкторе, результат которого допускает неинициализированную переменную экземпляра (например, не инициализированную при объявлении, а не в конструкторе). Но это не решение Gosling et. др., сняли в начале 90-х, так что вот и мы. (И я не говорю, что они сделали неправильный вызов.)

Однако я мог не отстать от локальных переменных по умолчанию. Да, мы не должны полагаться на компиляторы, чтобы перепроверить нашу логику, и никто этого не делает, но это все равно удобно, когда компилятор ее улавливает. : -)

3
ответ дан 24 November 2019 в 05:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: