... Это потому, что локальные переменные размещены в стеке, и поэтому мое новое сдувается, когда я покидаю метод?
Нет. Это из-за семантики передачи аргументов Java.
Аргументы Java передаются «по значению», но в случае типа объекта или массива передаваемое значение является ссылкой на объект / массив. Когда вы создаете и назначаете новый объект set для mySet
, вы просто устанавливаете локальную переменную / параметр. Поскольку Java использует передачу по значению, это не влияет на переменную foo
в методе main
.
Когда вы вводите метод test
, у вас есть две копии ссылки на экземпляр HashSet
, созданный в методе main
; один в foo
и один в mySet
. Затем ваш код заменяет ссылку в mySet
ссылкой на вновь созданный HashSet
, но эта новая ссылка не передается вызывающей стороне. (Вы можете изменить свой код, чтобы передать его обратно ... например, в результате использования метода test
. Но вы должны сделать это явно.)
ОК - однако - если бы я делал add или какую-либо другую операцию в моем вызове метода, это распределение было бы сохранено. Почему это так?
Это потому, что когда вы вызываете метод экземпляра, используя ссылку в foo
или mySet
, этот метод выполняется на объекте (HashSet
), на который ссылается ссылка. Предполагая, что две ссылки указывают на один и тот же объект, ваше «распределение будет сохранено». Точнее, вы можете наблюдать влияние операций на одну ссылку на объект с помощью операций на другие ссылки на тот же объект.
Просто помните, что Java-метод вызывает копирование ссылок на объекты, а не на сами объекты.
Кстати, вы не сможете добавлять элементы в набор, возвращаемый Collections.emptySet()
. Этот заданный объект является неизменным. Вызов (например) add
для него вызовет исключение.