Question

I have read Jon Skeet's [excellent] article about passing values in Java and seen this question on the same topic. I believe I understand them but what I am still wondering about is return values.

When an object is returned (as from a getter) then later altered in it's original scope (where it was gotten from) is the object reference owned by the variable to which the getter's return value was assigned altered? Boy that was a mouthful..
To borrow an example:

public class Dog {

    String dog ;

    public String getName()
    {
        return this.dog;
    }

    public Dog(String dog)
    {
        this.dog = dog;
    }

    public void setName(String name)
    {
        this.dog = name;
    }

    public static void main(String args[])
    {
        Dog myDog = new Dog("Rover");
        String dogName = myDog.getName();
        myDog.setName("Max");
        System.out.println(dogName);
    }
}

Does that print Rover or Max?

UPDATE Does print Rover.

The answers to my original question were great but Richard Tingle added a lot of useful information in the comments below so I thought I'd provide my test class for posterity.

public class Foo {
    private ArrayList<Integer> arrayList;

    public Foo() {
        arrayList = new ArrayList<Integer>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);

    }

    public ArrayList<Integer> getArrayList() {
        return arrayList;
    }

    public void addToArrayList(int item) {
        arrayList.add(item);
    }

    public static void main(String args[]) {
        Foo foo = new Foo();
        ArrayList<Integer> arrayList = foo.getArrayList();
        ArrayList<Integer> cloneList = (ArrayList<Integer>)foo.getArrayList().clone();
        System.out.println(arrayList.contains(4));
        System.out.println(cloneList.contains(4));
        foo.addToArrayList(4);
        System.out.println(arrayList.contains(4));
        System.out.println(cloneList.contains(4));
}

Output is false, false, true, false

Was it helpful?

Solution 3

As has been stated by many answers "Rover" will be printed because you have changed the actual string inside dog. You haven't changed the String itself (which you can't do as Strings are immutable, aka unchangeable).

public static void main(String args[])
{
    Dog myDog = new Dog("Rover"); //myDog contains STRING1 ("Rover")
    String dogName = myDog.getName(); //dogName is set to refer to STRING1 ("Rover")
    myDog.setName("Max"); //myDog name set to STRING2 ("Max") (STRING1 unaffected)
    System.out.println(dogName); //dogName still refers to STRING1 ("Rover"), "rover" printed
}

More general concept

This may give the impression that once you retrieve an internal object from another object using a getter it is entirely separate and you can change it as you see fit. This isn't always the case. Strings are immutable so you can't change their internal state. But if you accessed an object that was mutable (aka could be changed) and changed its internal state outside the Dog object then it would still affect the internal state of the Dog object. I will use an ArrayList to show this concept

public class Dog {

    public ArrayList<String> names=new ArrayList<String>();

    public ArrayList<String> getNames() {
        return names;
    }

    public void setNames(ArrayList<String> names) {
        this.names = names;
    }

    public static void main(String[] args){
         Dog dog=new Dog();
         dog.getNames().add("Rover");

         ArrayList<String> someArrayList=dog.getNames();
         someArrayList.add("Rex");

         System.out.println(dog.getNames().contains("Rex")); //prints true. dog's internal state effected from afar

         someArrayList=new ArrayList<String>(); //change someArrayList to refer to a whole new ArrayList
         someArrayList.add("bad");

         System.out.println(dog.getNames().contains("bad")); //prints false, someArrayList now points to a different ArrayList to the one internal to dog

    }

}

As you can see if you retrieve the arrayList and then add objects to it this would affect the ArrayList within Dog. If you retrieve the arrayList and set your variable to a completely different ArrayList then this won't affect the arrayList within Dog (because its a different ArrayList). Think of objects as being "no where in particular" and variables being addressed to those objects.

So an analogy; you (a Dog object) have an address book of houses you care about (other objects). You can change your address book to point to a different house, no one else will care about that. But if you post a letter to a house saying "paint the door green" everyone else with an address to that house will notice.

The general rule is if you change a variable to point to a different object only that variable is changed (like changing the address in your address book), this always involves an = and may involve a new (but may not and the new is hidden with strings) . On the other hand if you use a method on an object (like sending a parcel to a house to which you have an address) then everywhere that object is visible will see the change (this always involves a . to a method that is a setter (or otherwise changes the object, like add))

OTHER TIPS

It will print Rover once.

Reason :

 public void setName(String name)
    {
        this.dog = name;
    }

    public static void main(String args[])
    {
        Dog myDog = new Dog("Rover");
        String dogName = myDog.getName(); // here you are setting dogName to rover
        myDog.setName("Max");             // Here you are setting the String field of a Dog object to "Max" (just reassigning the reference and making it point to Max"
        System.out.println(dogName); // DogName is still Rover.
  // do  dogName = myDog.getName(); and print it.. And see what happens :)
    }

Does that print Rover or Max?

It will print Rover.

Because, you already retrieved the value from that Dog object. Later alternation to Dog object myDog, won't affect the value of variable dogName

When an object is returned (as from a getter) then later altered in it's original scope (where it was gotten from) is the object reference owned by the variable to which the getter's return value was assigned altered?

No, it won't alter the reference you assigned. Because you already retrieved the value.

It will be Rover because in the Dog object you just changed the reference from one String object ("Rover") to another ("Max"), but the dogName still references "Rover". BTW, you should run the code yourself.

By doing this:

String dogName = myDog.getName();  

you are creating a new String object containing "Rover" that is not referencing the attribute dog in the object myDog: they are completely independent.
So when you modify the dog value of myDog, this change won't affect the variable "dogName"

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top