Groovy (или Java) — передача по ссылке в объект-оболочку

Возможно ли в Java (или Groovy) передать объект по ссылке в объект-оболочку (например, список или карту)?

Пример кода (в Groovy):

def object = null
def map = [object: object]
object = new Object()

К сожалению, map.object остается нулевым, даже если объектная переменная этого не делает, поэтому очевидно, что первоначальное создание карты было выполнено по значению, а не по ссылке.

Можно ли создать список или карту с помощью ссылок, чтобы при изменении объекта вне списка или карты изменение отражалось внутри объекта-оболочки?


person Harry Muscle    schedule 15.08.2014    source источник
comment
Нет, это невозможно   -  person tim_yates    schedule 15.08.2014


Ответы (3)


Нет, ты не можешь этого сделать. В зависимости от того, что вы действительно пытаетесь сделать, может помочь что-то вроде этого:

class MyWrapper {
    def wrappedValue
}

def object = new MyWrapper()
def map = [object: object]

object.wrappedValue = 'This is a new value'
assert map.object.wrappedValue == 'This is a new value'

Это, конечно, код Groovy. Вы можете сделать то же самое в Java, только с небольшим количеством кода. Идея будет та же.

person Jeff Scott Brown    schedule 15.08.2014
comment
AtomicReference — это универсальная и поточно-ориентированная конструкция JDK, допускающая такую ​​упаковку. - person GPI; 15.08.2014
comment
@GPI В его описании недостаточно контекста, чтобы понять, является ли безопасность потоков проблемой. Если все это происходит в методе и ничто из этого не ускользает от метода, безопасность потоков может не иметь никакого значения. Использование вашей собственной оболочки, или предоставленной JDK, или предоставленной какой-либо другой библиотекой, конечно, все это варианты. - person Jeff Scott Brown; 15.08.2014
comment
Код, который я показываю, демонстрирует, что способ сделать то, что кажется интересным для исходного вопроса, — это поместить в карту что-то, что имеет ссылку на реальное значение. - person Jeff Scott Brown; 15.08.2014

Можно с замыканиями, но их нужно вызывать:

def object = null
def map = [object: { object }]
object = new Object()

assert map.object() != null
person Will    schedule 15.08.2014

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

Так, например, когда вы делаете это:

Object reference1 = new Object();
// reference1 now equals some adress in memory, e.g. 0001
Object reference2 = reference1;
// reference2 now equals the value of reference1 - i.e. 0001

Теперь, когда мы делаем это:

reference1 = new Dog();
// reference1 is now assigned a new value, which is the memory adress
// of the new Dog object.

Нет никаких причин, чтобы это повлияло на reference2. reference2 по-прежнему владеет адресом 0001. И это именно то, что вы делаете.

Давайте посмотрим, что происходит в фрагменте кода, который вы разместили:

def object = null

Создается новая ссылка с именем object, и ей не назначаются адреса, т. е. null. (Объект не создается, только ссылка).

def map = [object: object]

Создается новая ссылка с именем map. Ему назначается новый объект карты с записью с именем object. Карте передается значение ссылки с именем object.

Как вы помните, значение ссылки object в настоящее время равно null. Таким образом, это значение передается (то есть передается по значению) ссылке в объекте карты, который теперь также содержит null.

object = new Object()

Ссылке object в основной программе присваивается новое значение - новое Object. Теперь он содержит адрес нового объекта, например. 0001.

При этом вы ставите значение в переменную object — вы ставите адрес объекта (где раньше было null).

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

Это важное различие между объектом и ссылкой.

person Aviv Cohn    schedule 15.08.2014
comment
Неправда, кажется, что groovy всегда проходит по ссылке, приведенные выше примеры изменяют основной объект. Посмотрите этот простой пример в отличной консоли def g = ["1","2","3"]; println g; def r = g; r.remove('1'); println r; println g​​​​​​​​​​​ - person rboy; 25.10.2017
comment
См. это stackoverflow.com/questions/25729492/ - person rboy; 25.10.2017