7

I was kind of baffled when I saw the following code did not work as expected.

I thought Java always passed variables by references into functions. Therefore, why can't the function reassign the variable?

public static void main(String[] args) {

  String nullTest = null;

  setNotNull(nullTest);

  System.out.println(nullTest);
}

private static void setNotNull(String s) {
  s = "not null!";
}

This program outputs null.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
Will
  • 1,622
  • 4
  • 25
  • 39
  • That doesn't mean anything. You can instantiate whatever you can instantiate, but you can't change the value the caller passed you. – user207421 Aug 14 '10 at 10:31

4 Answers4

22

References to objects are passed by value in Java so assigning to the local variable inside the method doesn't change the original variable. Only the local variable s points to a new string. It might be easier to understand with a little ASCII art.

Initially you have this:

------------
| nullTest |
------------
     |
    null

When you first enter the method setNotNull you get a copy of the value of nullTest in s. In this case the value of nullTest is a null reference:

------------    ------------
| nullTest |    |    s     |
------------    ------------
     |               |
    null            null

Then reassign s:

------------    ------------
| nullTest |    |    s     |
------------    ------------
     |               |
    null         "not null!"

And then leave the method:

------------
| nullTest |
------------
     |
    null
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • So then what about objects? I've gotten generic answers with a big anti-noob attitude and have yet gotten a good explination – TheLQ Aug 14 '10 at 03:56
  • great way to show memory structures. +1 – raja kolluru Aug 14 '10 at 05:15
  • @ Lord.Quackster There is no difference between the way java handles objects as opposed to primitive types. Both are passed by value. However since java operates with "references" of objects, it is possible to mutate the passed reference. But since the reference itself is passed by value, the reference cannot be reset to something else. – raja kolluru Aug 14 '10 at 05:25
  • @TheLQ: I like to say that Java passes by copy-of-the-variable-value. In case of primitives the copied valued is the value itself; for objects the copied value is something that tells the JVM how to retrieve the Object in the Heap Memory. I do not like to use Strings when talking about this because they are immutable (still, String is an Object). More here: http://stackoverflow.com/questions/40480/is-java-pass-by-reference/7034719#7034719 – Marsellus Wallace Aug 23 '11 at 22:08
3

Java doesnt pass by reference, it passes the value of the reference. When you are assigning s="not null", you are reassigning that value.

akf
  • 38,619
  • 8
  • 86
  • 96
1

I was hoping to do something like setNotNull(MyObject o) without using o = setNotNull(o)

Simply, you cannot. The closest you will get is something like this:

public class MyRef<T> {
    private T obj;

    public T get() {
        return obj;
    }

    public void set(T obj) {
        this.obj = obj;
    }

    public void setNotNull(T obj) {
        if (this.obj == null) {
            this.obj = obj;
        }
    }
}

MyRef<MyObj> ref = new MyRef<MyObj>();
ref.setNotNull(xyz);
System.err.println(ref.get());

which is all rather clunky, and probably not worth the effort.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0
s =

this is why. you are assigning to s, not modifying the object that s points to.

Bwmat
  • 4,314
  • 3
  • 27
  • 42