views:

104

answers:

4

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 the function assign 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!";
}

outputs "null"

+11  A: 

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
+1, very expressive!
Nikita Rybak
So then what about objects? I've gotten generic answers with a big anti-noob attitude and have yet gotten a good explination
TheLQ
great way to show memory structures. +1
raja kolluru
@ 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
+2  A: 

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
A: 
s =

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

Bwmat
+1  A: 

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