2016-06-24 2 views
1

я прочитал где-то, читая о System.out.print, что в System классе, есть декларация «из» в качестве статической переменной в PrintStream типа класса следующим образом: public static final PrintStream out;Объявляя переменную типа класса без инициализации его

Это вызвало во мне вопрос, что именно происходит, если мы просто объявляем переменную определенного типа класса и не инициализируем его, не вызывая никакого конструктора? В приведенном выше примере «out» объявлен статическим и окончательным, но я ищу обобщенный ответ.

+0

'System.out' (вместе с in и err) является единственным исключением. Это, предположительно, поле «final», но его значение может быть изменено (косвенно). – biziclop

ответ

0

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

Если вы не инициализируете объект, вы получаете нулевой указатель. Этот объект просто не существует, в нем нет полей или методов.

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

+0

«они связаны с классом» - поэтому мы можем вызывать «out» как System.out как свою переменную класса, понимаем, но если «out» является нулевым указателем или ссылкой, как мы можем позвонить метод 'print' класса PrintStream' через 'out', как в 'System.out.print'? – amsquareb

+0

@amsquareb Это не нулевой указатель, он уже инициализирован –

+0

Но как его уже инициализировали? @JonSkeet также говорит об этом в первом ответе на этот вопрос: «Тогда, как и любое другое поле, оно начинается с значения по умолчанию, которое для типов ссылок (классы, интерфейсы, перечисления) является нулевой ссылкой». Поэтому я предполагаю, что он имел в виду, что это нулевая ссылка/указатель. – amsquareb

4

Это вызвало у меня вопрос, что именно происходит, если мы просто объявим переменную определенного типа класса и не инициализируем его, не вызывая никакого конструктора?

Тогда, как и любой другой области, он начинается с его значение по умолчанию - что для ссылок типы (классы, интерфейсы, Перечисления) является null ссылки. Из section 4.12.5 of the JLS:

Каждая переменная в программе должна иметь значение до того, как используется его значение:

  • Каждая переменная класса, переменная экземпляра, или компонент массива инициализируется значением по умолчанию при его создании (§15.9, §15.10.2):
  • Для типа byte значение по умолчанию равно нулю, то есть значение (byte)0.
  • Для типа short значение по умолчанию равно нулю, то есть значение (short)0.
  • Для типа int значение по умолчанию равно нулю, то есть 0.
  • Для типа long значение по умолчанию равно нулю, то есть 0L.
  • Для типа float значением по умолчанию является положительный ноль, то есть 0.0f.
  • Для типа double значением по умолчанию является положительный ноль, то есть 0.0d.
  • Для типа char значением по умолчанию является нулевой символ, то есть '\u0000'.
  • Для типа boolean значением по умолчанию является false.
  • Для всех ссылочных типов (§4.3) значение по умолчанию: null.

System.out немного особенным - это окончательное, но может быть изменен с помощью System.setOut. Я попытался бы избежать обобщения любого другого поведения, основанного на этом.

Смежные вопросы