3

I have the following code. I can't, however, understand it's behavior about pass by value and reference.

class Dog{
    String name;
    int x=100;
    
    Dog(String name){
        this.name = name;
    }
    
    public String getName(){
        return this.name;
    }
}
class Demo{
    public static void main( String[] args ){
        Dog aDog = new Dog("Tom");
        foo(aDog);

        if (aDog.getName().equals("Tom")) { //true
            System.out.println( "Java passes by value."+ aDog.getName());
            System.out.println( aDog.x);

        } else if (aDog.getName().equals("Taz")) {
            System.out.println( "Java passes by reference." );
        }
    }

    public static void foo(Dog d) {
        ++d.x;
        d = new Dog("Taz");
        ++d.x;
    }
}

This will provide output as

Java passes by value.Tom

101

Why is the output 101? I was expecting output 102.

Community
  • 1
  • 1
Saveendra Ekanayake
  • 3,153
  • 6
  • 34
  • 44
  • 1
    http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value?rq=1 might be worth a read –  Sep 01 '15 at 06:09
  • 2
    Java is always **Pass By Value** –  Sep 01 '15 at 06:12

4 Answers4

4

You're incrementing x twice, but on different dogs. Look at this code:

public static void foo(Dog d) {
    ++d.x;
    d = new Dog("Taz");
    ++d.x;
}

Initially, d refers to the dog with a name of Tom, with x=100. That isn't a copy of the original object - it's a reference to the same object. Java passes the reference by value, which isn't the same as either passing an object by value or passing an object by reference. It's important to understand that the value of aDog in main isn't a Dog object - it's a reference to a Dog object. The value of that reference is passed, by value, to your foo method... so the initial value of d is the same as the value of aDog. Further changes to the d variable itself (rather than the object its value refers to) do not change the aDog variable.

So, looking at the rest of foo:

  • After the ++d.x, d refers to the dog with a name of Tom, with x=101.
  • After d = new Dog("Taz"), d refers to a dog with a name of Taz, with x=100.
  • After the ++d.x, d refers to the dog with a name of Taz, with x=101.

The calling code only ever knows about the dog with a name of Tom, so it prints out Tom 101.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks @Jon But the next thing is why it prints Tom Object details without printing Taz object details. According to my opinion I thought java pass copy of Tom object to foo method. But t will not pass copy according to this. – Saveendra Ekanayake Sep 01 '15 at 06:15
  • 1
    @SaveendraSriEkanayake: No, it passes a copy of the *reference*, as the initial value of `d`. I've edited the answer to give more information - see if that helps. – Jon Skeet Sep 01 '15 at 06:15
3

You increment x once, on the dog that was given to the method ("Tom").

Then you create a new dog, called Taz.

You then increment x for that second dog. It won't affect the original one, and both dogs will be at 101.

As for why the calling method still refers to "Tom", even though you changed your local variable to point at "Taz": That's because a local variable is just that: local to the place it is used. The caller does not care about what you do with it later, its own variable will still point at "Tom".

Because Java does not support pass-by-reference or "out parameters", there is nothing the called function can do to change the value of variables in the calling function.

But note that objects are not stored in variables. Only a pointer to them is stored there. The actual object instance itself is in a shared location (the program heap memory). So the called method can indeed change the object. But it cannot assign a different object into the calling function.


Takeaway: Make your local variables final, especially method parameters. Then you cannot reuse the same variable for two different things, and the code becomes less confusing.

Thilo
  • 257,207
  • 101
  • 511
  • 656
2

Java is always Pass By Value:

main():

Dog aDog = new Dog("Tom"); // {name="Tom", x=100}

foo():

++d.x;                     // {name="Tom", x=101}
d = new Dog("Taz");        // {name="Taz", x=100}
++d.x;                     // {name="Taz", x=101}

However, you can get entirely new copy but you need to return it.

In main(): update this line

foo(aDog);

to

aDog = foo(aDog);

also update foo() as:

public static Dog foo(Dog d) {
  ...
  return d;
}
-1

When you use the new keyword like this d = new Dog("Taz");
You create a new Dog, the new Dog it's called Taz and have x=101, so you don't increment d.x 2 times for the same Dog

John Moutafis
  • 22,254
  • 11
  • 68
  • 112