Что происходит, когда объект только определен? - PullRequest
0 голосов
/ 11 января 2019

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

Например:

public class MainClass {
 public static void main (String[] args){
  Object foo;
 }
}

Указывает ли foo на область памяти? Меняется ли это поведение между различными языками программирования?

Заранее спасибо.

Редактировать: Я знаю, что объект будет указывать на ноль при использовании, но мне интересно знать, что происходит сразу после того, как объект был определен, но еще не создан. Есть ли в этом случае ссылка на память?

Ответы [ 3 ]

0 голосов
/ 11 января 2019

В Java вы можете рассматривать переменные объекта как указатели. По умолчанию они ничего не указывают, выделяется только сам указатель (например, 8 байт в стеке).

Вы можете указать, чтобы он указывал на фактический экземпляр объекта, выделив этот объект и присвоив переменную:

Object foo; // points to nothing (and may not be used)

foo.toString(); // compile error: The local variable obj may not have been initialized

foo = new Object(); // points to an instance of a new Object

foo = null; // again points to nothing, but is now initialized

foo.toString(); // will compile, but throw NullPointerException at run time

Это принципиально отличается от C или C ++, где Object foo; фактически будет локальным объектом, размещенным в стеке. Java никогда не размещает объекты в стеке, только примитивные типы или указатели.

0 голосов
/ 11 января 2019

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

Предположим, что мы говорим о Java здесь.

Сначала я должен исправить ваше неверное описание. (По причинам, которые станут очевидными ...)

Это не определение объекта . Скорее, объявляет переменную . Идентификатор foo обозначает переменную . Поскольку тип переменной (в данном случае) Object, который является ссылочным типом, переменная может содержать либо ссылку на объект Java , либо null.

Указывает ли foo на область памяти?

Ответ немного сложен.

  • Если переменная инициализирована, она либо будет указывать на некоторый объект, либо будет содержать null.

  • Если переменная НЕ инициализирована, то это зависит от типа переменной, о которой мы говорим:

    • Для поля класса (статического или экземпляра) переменная, которая не инициализирована явно, имеет значение Инициализировано по умолчанию * null.

    • Для переменной, которая является параметром или переменной catch, семантика языка Java гарантирует, что переменная всегда инициализируется ... так что это спорный вопрос.

    • Для локальной переменной JLS не говорит, что она содержит, прежде чем ей будет присвоено значение. Вы могли бы сказать, что значение является неопределенным. Однако JLS (и во время выполнения, верификатор файла классов JVM) гарантируют, что программа не может использовать локальную переменную, которая находится в неопределенном состоянии. (Это ошибка компиляции в коде Java для чтения переменной, которая не была определенно назначена .) Так что действительно не имеет значения, что содержит переменная на самом деле .

Обратите внимание, что в чистой Java переменная никогда не может содержать значение, которое не было установлено присваиванием или инициализацией. Таким образом, переменная никогда не может ссылаться на случайный адрес памяти. (Если вы используете нативный код, возможно, что код повредит переменную, чтобы что-то содержать. Но не делайте этого преднамеренно, так как это может привести к серьезному сбою JVM.)

Меняется ли это поведение между различными языками программирования?

Э-э-э ... да. Например, в C и C ++ программа может использовать значение переменной-указателя, которая не была инициализирована. Поведение, которое следует, является неопределенным .

0 голосов
/ 11 января 2019

В Java, foo будет указывать на «ноль», когда он определит в классе, и foo ничего не укажет, где он определен в функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...