Меняет ли ключевое слово "new" значение ссылки на объект? - PullRequest
2 голосов
/ 30 мая 2009

Допустим, у меня есть несколько экземпляров классов, которые служат различным целям, поэтому я хочу иметь возможность ссылаться на них напрямую по имени:

SomeObject aardvark = new SomeObject();
SomeObject llama = new SomeObject();
SomeObject tiger = new SomeObject();
SomeObject chicken = new SomeObject();

Но тогда я также хочу их массив для легкой итерации:

SomeObject[] animals = {aardvark, llama, tiger, chicken};

Мой вопрос такой. Что происходит, когда я делаю это:

llama = new SomeObject();

Я буду создавать совершенно новый объект ламы. Как это влияет на мой массив животных? Будет ли он ссылаться на объект NEW llama или как-то еще ссылаться на копию старого?

Я знаю, что Java - это «передача по значению», но я все еще путаюсь с подобными вещами. Когда я использую ключевое слово NEW, изменяется ли значение этой ссылки на объект? Спасибо!

Ответы [ 9 ]

7 голосов
/ 30 мая 2009

На ваш массив животных это не повлияет.

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

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
llama -------------> SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

Когда вы делаете это:

llama = new SomeObject();

вы создаете новый SomeObject, а затем меняете ламу, чтобы он указывал на него.

chicken ---------------------------> SomeObject
tiger ---------------------> SomeObject  ^
                     SomeObject  ^       |
aardvark --> SomeObject  ^       |       |
                 ^       |       |       |
                 |       |       |       |
animals -----> {[0],    [1],    [2],    [3]}

llama -------> SomeObject

Важно помнить, что (не примитивные) переменные и элементы массива являются просто ссылками на объекты, и всякий раз, когда вы видите «x = y;» (даже если x является индексом массива) это означает «заставить x ссылаться на то, к чему относится y в настоящее время ».

2 голосов
/ 30 мая 2009

Ваш массив animals будет содержать указанную вами ссылку ("старую" версию), когда вы назначаете другую ссылку (например, "новую" версию) для имени llama.

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

1 голос
/ 30 мая 2009

Это не имеет ничего общего ни с передачей по значению или передачей по ссылке, ни с new. Здесь вам нужно понять разницу между переменной, выражением и ссылкой. Ключевая строка такова:

SomeObject[] animals = {aardvark, llama, tiger, chicken};

Это синтаксический сахар для создания массива и заполнения его ссылками. Внутри фигурных скобок происходит то, что существует список выражений, которые оцениваются. Эти выражения являются переменными, которые вы объявили и инициализировали ранее, но переменные - это просто имена адресов памяти, содержащих ссылки на объекты. Выражения оцениваются для содержимого адресов памяти (ссылок), которые помещаются в массив - это неявно создает копии ссылок. Поэтому скопированные ссылки полностью независимы от переменных. Может быть, это станет легче понять, если учесть это:

SomeObject[] animals = {aardvark, llama, tiger, new SomeObject()};

Здесь последнее выражение использует new для создания объекта. Выражение оценивается как ссылка на вновь созданный объект, который помещается в массив как ссылка only на этот объект - там нет никакой переменной , которая ссылается на него напрямую! *

1 голос
/ 30 мая 2009

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

0 голосов
/ 30 мая 2009

Когда вы используете отладчик, вы можете видеть, когда у вас есть тот же объект или новый объект. Это также может помочь вам, когда один и тот же объект виден несколькими способами.

0 голосов
/ 30 мая 2009

Массив должен оставаться как есть, так как все элементы массива на самом деле являются указателями на точку в куче, где можно найти актуальную информацию.

Итак, в вашем массиве есть ссылка на некоторую точку в куче. Затем вы создаете другую точку в куче, и контейнер удерживает ее, но другая все еще существует и будет указывать на старое местоположение.

Итак, ваш массив должен оставаться нетронутым. Обратите внимание, что единственный способ связаться через элемент x'd рассматриваемого массива.

0 голосов
/ 30 мая 2009

Изменение llama не изменит массив. Как вы сказали, Java является «передачей по значению». Думайте о llama как о маленькой коробочке, в которой указано, где можно найти ламу. Когда вы создаете массив, ссылка внутри llama копируется в массив. Поэтому, когда вы измените llama позже, вы не будете связываться с массивом.

0 голосов
/ 30 мая 2009

нет, ваш пример выглядит так:

int a = 1;
int b = 2;
int[] ary = { a, b };
a = 2;
// ary[0] still yields 1
0 голосов
/ 30 мая 2009

Нет, не будет. Он создает новый экземпляр, и значение выражения будет ссылкой на созданный экземпляр. Назначение будет просто установить переменную для нового объекта. Это не повлияет на другие ссылки на предыдущий объект.

По сути, вы можете думать об этом как о двух отдельных операциях:

SomeObject newInstance = new SomeObject();
oldInstance = newInstance; 

oldInstance содержит только ссылку, и назначение изменится именно так.

Это совершенно не связано с передачей по значению. Вы нигде не пропускаете никаких объектов.

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