-1

I am confused about how Java deals with aggregation within objects, and in particular referencing of objects. It seems like objects will keep a reference to an aggregated object when it is passed as a parameter, rather than copying it like I've been lead to believe.

Say I have a basic class called Foo which contains a string attribute, print function, and setter for the text attribute.

public class Foo {

    private String text;

    public Foo(String text) {
        this.text = text;
    }

    public void print() {
        System.out.println(text);
    }

    public void setText(String text) {
        this.text = text;
    }

}

And a class called Bar which contains an attribute of type Foo, and a method called print which calls foos print method.

public class Bar {

    private Foo foo;

    public Bar(Foo foo) {
        this.foo = foo;
    }

    public void print() {
        this.foo.print();
    }

}

If I define an instance of Foo, pass it into a new instance of Bar, and then call bars print method it will print "hello" as I expected. However if I then set the text of the original instance of foo to "Edited" using its setter method, bars print method will also print "Edited".

public static void main(String[] args){

    Foo foo = new Foo("Hello");
    Bar bar = new Bar(foo);
    bar.print();
    foo.setText("Edited");
    bar.print();

}

Console Output

The Bar object appears to be keeping a reference to the Foo object even though I passed it as a parameter. I'm sure I am missing something trivial here, and I just wanted someone to explain this clearly.

Max
  • 37
  • 1
  • 6

2 Answers2

3

"I'm sure I am missing something trivial here"

Not really. What you see is not a bug, it is a feature. Passing objects around in java means passing around references to them. Objects aren't "cloned" unless the code explicitly requests this through .clone(). Searching on this site for "is java pass-by-value or pass-by-reference" should help you find all the detailed explanation you need.

Erwin Smout
  • 18,113
  • 4
  • 33
  • 52
  • A feature that I frequently use. I didn't know about .clone() though, thanks. What is the meaning of "pass by value" then? – Max Aug 18 '18 at 21:48
  • 1
    @Max As suggested by the Answer, search Stack Overflow for those technical phrases *pass-by-value* and *pass-by-reference*. They have been covered many times already. No point in rehashing them here. – Basil Bourque Aug 19 '18 at 16:42
0

Reference copied, not object

It seems like objects will keep a reference to an aggregated object when it is passed as a parameter, rather than copying it like I've been lead to believe.

No, the object is not copied.

The reference (pointer) is copied when passed as an argument to a method. The object (the referent, the thing to which the pointer points) is not copied.

The pointer is really an address in memory someplace (though not seen as such by us Java programmers). That address, basically a number, is being copied when passed into the other method. But the object is left untouched, unaware of any references.

Here's a diagram of several Cat objects in memory. Three of the five are candidates for garbage-collection because they have no references remaining, no pointers pointing to them. At first Lilly Mae cat has one pointer pointing to it.

Cat c = new Cat( "Lilly Mae" ) ;

The c variable is not holding a Cat, it holds the address elsewhere in memory where you can find the Cat object. Think of that line as saying:

variable-holding-pointer-that-can-only-point-to-objects-of-class-Cat c = instantiate-new-object-of-type-Cat-and-return-a-pointer-to-its-location-in-memory( "Lilly Mae" ) ;

Then we pass that pointer as a argument to another method.

Human h = SubservientHumanLocator.findFirstAvailable() ;
h.feedCat( c ) ;  // Passing a copy of the address of Lilly Mae to this other object’s method.

After the reference to the Cat is passed to the Human, we still have only one hungry cat. We did not clone the cat. We now have two references, both pointing to same original Cat object.

Here is a diagram of state before and after the Human::feedCat call.

enter image description here

After calling on the human to feed the cat, the variable c may fall out of scope. After feeding the cat, the Human object h will likely let its copied reference also fall out of scope. Then, if no other references had been made, and with no existing references remaining, our well-fed Cat object will become a candidate for garbage-collection.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154