Java передается по значению. значение ссылки на объект - это объект ссылка , а не сам объект. И поэтому метод toCommand
получает копию значения, которое является ссылкой на объект & mdash; тот же объект, на который ссылается вызывающая сторона.
Это точно так же, как когда вы ссылаетесь на объект из двух переменных:
StringBuffer buf1;
StringBuffer buf2;
buf1 = new StringBuffer();
buf2 = buf1; // Still ONE object; there are two references to it
buf1.append("Hi there");
System.out.println(buf2.toString()); // "Hi there"
бесплатный ASCII art:
+--------------------+
buf1--------->| |
| === The Object === |
| |
buf2--------->| Data: |
| * foo = "bar" |
| * x = 27 |
| |
+--------------------+
Еще один способ думать о том, что JVM имеет основной список всех объектов, проиндексированных по идентификатору. Мы создаем объект (buf1 = new StringBuffer();
), а JVM назначает объекту идентификатор 42 и сохраняет этот идентификатор для нас в buf1
. Всякий раз, когда мы используем buf1
, JVM получает значение 42 из него, ищет объект в своем основном списке и использует объект. Когда мы делаем buf2 = buf1;
, переменная buf2
получает копию значения 42, и поэтому, когда мы используем buf2
, JVM видит ссылку на объект # 42 и использует тот же объект. Это не буквальное объяснение (хотя и со стратосферной точки зрения, и если вы читаете «JVM» как «JVM и диспетчер памяти и ОС», это не за миллион миль от него), но полезно для размышления о том, какие ссылки на объекты на самом деле есть.
С этим фоном вы можете видеть, как toCommand
получает ссылку (42 или что-то еще), а не фактические StringBuffer
данные объекта. И поэтому операции над ним ищут его в главном списке и изменяют его состояние (поскольку оно содержит информацию о состоянии и позволяет нам изменять его). Вызывающий видит изменения в состоянии объекта, потому что объект хранит состояние, ссылка просто указывает на объект.
В любом случае ... писать код наподобие этого на Java следует считать плохой практикой, верно?
Совсем нет, это нормальная практика. Было бы очень трудно использовать Java (или большинство других языков ООП) без этого. Объекты большие по сравнению с примитивами, такими как int
и long
, и поэтому их дорого обходить; ссылки на объекты имеют размер примитивов, поэтому их легко передавать. Кроме того, наличие копий вещей затрудняет взаимодействие различных частей системы. Наличие ссылок на общие объекты делает это довольно простым.