views:

169

answers:

5

I read this excellent article and it make sense: Java is strictly pass by value; when an object is a parameter, the object's reference is passed by value.

However, I'm totally confused as to why the following snippet could possibly work. Foo has a String member variable a which is immutable and needs to be burned in every time. The first method of burning (commented out) should work fine and it does. The second method set's a's reference to the value that was passed. It should not work if newstr is a temporary variable. The expected output results are:

Totally temp
NULL

However, I get

Totally temp
Totally temp

Why? Is it just pure luck that the temporary variable reference is still good?

public class Foo {
    String a;
    public Foo(){}
    public void burna(String newstr){
           // a = new String(newstr);
           a = newstr; /*this should not work: */ 
        }
}

public class foobar {
    Foo m_foo;
    public foobar(){};
    public void dofoo(){
        String temp = new String("Totally temp\n");
        m_foo.burna(temp);
        System.out.print(m_foo.a);
    }

}

 public static void main(String[] args) {
        Foo myfoo = new Foo();
        foobar myfoobar = new foobar();

        myfoobar.m_foo = myfoo;
        myfoobar.dofoo();
        System.out.print(myfoo.a);

    }
+11  A: 

Foo has a String member variable a which is immutable and needs to be burned in every time.

No it doesn't: it's not marked as final:

public class Foo {
    String a;
    ...
}

The variable is perfectly mutable - you can change it to refer to a different string at any time, which is what you do in the burna method.

I don't currently see why you think this wouldn't work:

public void burna(String newstr){
    a = newstr; /*this should not work: */ 
}

That's setting the value of a to be the value of newstr - which is a reference to a string (or null). That's all it's doing. I'm not sure what you mean by "burning in" a variable though.

You're calling burna and passing in a reference to a string with the text "Totally temp\n" - so a is set to a reference to that string.

What do you mean by "It should not work if newstr is a temporary variable." There's no such thing as a "temporary variable". There's a local variable - but an object isn't destroyed just because a variable which refers to it goes out of scope. Is that what's confusing you?

Your program has several things going on - the foobar class probably isn't helping you in terms of understanding. Could you try to simplify your code to the point where it's still confusing you, but there's less going on? Then we could isolate the source of confusion more precisely.

Jon Skeet
...a = newstr means (as Strings are objects) "set a to reference the same object as referenced by newstr".
Will A
@Will A: I prefer to view them just as values, that happen to be references. That's more consistent with primitive types then - assignment just copies the value from the RHS to the variable on the LHS. Nice and simple.
Jon Skeet
Totally agreed - everything passed by value, very straightforward.
Will A
"an object isn't destroyed just because a variable which refers to it goes out of scope. Is that what's confusing you?" Yes! So, if I create a local variable and store its reference somewhere else (as in this case), it won't be garbage collected... until, myfoobar gets garbage collected (in this case)?
Pete
Just tried nulling out myfoobar and foo's string was still safe. So I guess it just won't be garbage collected (unless of course myfoo went away). Is that correct?
Pete
@Peter: Absolutely. I suggest you read up on garbage collection in a good Java book :)
Jon Skeet
+2  A: 

There are two references to the string "Totally temp\n". One is temp the other is a in the Foo object. At the end of dofoo temp goes out of scope, so that's one reference less. However you still have the other reference, so the string is not garbage collected.

sepp2k
+2  A: 

The String object is immutable, but the Foo object is not. myfoobar.m_foo and myfoo point to the same object and thus share the a member.

Philipp
+3  A: 

The problem appears to be that you don't understand how garbage collection works. As long as at least one reference to an object remains valid, that object will not be collected.

Donnie
You are correct, and that was the source of my problem.
Pete
+1  A: 

You might be used to the way variables and objects work in C++.

Variables of non-primitive types are always references to objects in Java, unlike in C++, where variables represent objects themselves.

Objects in Java are always allocated on the heap. Objects are never on the stack* as "temporary variables", like in C++.

*: actually, the JVM might do some optimizations and put objects on the stack, but that's not relevant for understanding the concept of how variables and objects work in Java.

Jesper