Java - Object state does not change after method call

Anand Hemmige picture Anand Hemmige · Aug 3, 2012 · Viewed 47.7k times · Source

Beginner java question, but I cannot understand how call-by-Value ( or Reference ) is working in the example below -

How come the String value is not modified after it exits the method while my custom String Object is. ? Same with other classes like Date..

public class StringMadness {

public static void main(String[] args) {
    String s = "Native String";
    CustomStringObject cs = new CustomStringObject();
    System.out.println("Custom String Before: " + cs.str);
    hello(cs);
    System.out.println("Custom String After: " + cs.str);

    System.out.println("Native String Before: " + s);
    hello(s);
    System.out.println("Native String After: " + s);
}

private static void hello(String t) {
    t = "hello " + t;
}

private static void hello(CustomStringObject o) {
    o.str = "hello " + o.str;
  }
}

class CustomStringObject {

String str = "Custom String";
}

Answer

Jon Skeet picture Jon Skeet · Aug 3, 2012

Compare these two methods:

private static void hello(String t) {
    t = "hello " + t;
}

private static void hello(CustomStringObject o) {
    o.str = "hello " + o.str;
}

In the first case, you're assigning a new value to t. That will have no effect on the calling code - you're just changing the value of a parameter, and all arguments are passed by value in Java.

In the second case, you're assigning a new value to o.str. That's changing the value of a field within the object that the value of o refers to. The caller will see that change, because the caller still has a reference to that object.

In short: Java always uses pass by value, but you need to remember that for classes, the value of a variable (or indeed any other expression) is a reference, not an object. You don't need to use parameter passing to see this:

Foo foo1 = new Foo();
Foo foo2 = foo1;
foo1.someField = "changed";
System.out.println(foo2.someField) // "changed"

The second line here copies the value of foo1 into foo2 - the two variables refer to the same object, so it doesn't matter which variable you use to access it.