1

Is it possible in Java (or Groovy) to pass an object by reference into a wrapper object (ie: List or Map)?

Example code (in Groovy):

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

Unfortunately map.object remains null even though the object variable doesn't, so obviously the original creation of the map was done by value not by reference.

Is it possible to create a List or Map via references so that when the object outside the List or Map changes the change is reflected inside the wrapper object?

DavidPostill
  • 7,734
  • 9
  • 41
  • 60
Harry Muscle
  • 2,247
  • 4
  • 38
  • 62

3 Answers3

1

No, you can't really do that. Depending on what you are really trying to do, something like this might help:

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'

That of course is Groovy code. You can do the same sort of thing in Java, just with a little more code. The idea would be the same.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • 1
    `AtomicReference` is a generic and thread-safe JDK construct that allows this kind of wrapping. – GPI Aug 15 '14 at 15:50
  • @GPI There isn't enough context in his description to know if thread-safety is a concern. If all of that is happening in a method and none of it escapes the method, thread-safety may not be of any consequence. Using your own wrapper, or one provided by the JDK or one provided by some other library, all of those are options of course. – Jeff Scott Brown Aug 15 '14 at 15:55
  • The code I show demonstrates that a way to kind of do what the original question seems to be interested in is put something in the Map that has a reference to the real value. – Jeff Scott Brown Aug 15 '14 at 15:56
1

You can with closures, but they need to be invoked:

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

assert map.object() != null
Will
  • 14,348
  • 1
  • 42
  • 44
0

In Java (and I assume in Groovy too), when you pass an object - you pass the value of the reference to it.

So for example when you do this:

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

Now, when we do this:

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

There is no reason for it to affect reference2. reference2 still holds the adress 0001. And that's exactly what you're doing.

Let's examine what's happening in the piece of code you posted:

def object = null

A new reference named object is created, and assigned no adresss, i.e. null. (No object is created, only a reference).

def map = [object: object]

A new reference named map is created. It is assigned a new map object, with an entry named object. The map is passed the value of the reference named object.

As you remember, the value of the object reference is currently null. So this value is passed (i.e. pass-by-value) to the reference in the map object, which now holds null too.

object = new Object()

The reference object in the main program is assigned a new value - a new Object. It now holds the adress of the new object, e.g. 0001.

When you do this, you put a value in the object variable - you put an adress of an object (where was previously null).

If you think about it, there's no reason for it to affect the map. The map has a completely different reference. Just becasue previously both references held the same adress memory, i.e. referenced the same object (or in this case, no object since the adress was null), doesn't mean that when the value of one reference is changed (i.e. it's assigned a different value in memory), the value of the other has to change too.

This is an important distinction between an object and a reference.

Aviv Cohn
  • 15,543
  • 25
  • 68
  • 131
  • Not true, groovy always seems to pass by reference, you examples above does modify the primary object. See this simple example in a groovy console `def g = ["1","2","3"]; println g; def r = g; r.remove('1'); println r; println g​​​​​​​​​​​` – rboy Oct 24 '17 at 22:41
  • See this https://stackoverflow.com/questions/25729492/copy-object-properties-to-a-map-by-value-not-by-reference – rboy Oct 24 '17 at 22:47
  • @rboy, I think you're confusing "pass by copy" due to this being a copy of the reference. In your example both r and g have the same value/reference. You can use either r or g to update the single object that they both point to. For me, the easiest way to understand it is method calls. You can pass a variable to a method and then in that method you can invoke methods on that parameter and it affects the same object, but if you change what that parameter points to (i.e. foo = [:]) you don't affect what the caller's variable is pointing to, because it's reference was by copy. – Greg Biles Jul 03 '23 at 21:25