tags:

views:

5797

answers:

7

I'd like semantics similar to C#'s ref keyword.

+39  A: 

Java is confusing because everything is passed by value. However for a parameter of reference type (i.e. not a parameter of primitive type) it is the reference itself which is passed by value, hence it appears to be pass-by-reference (and people often claim that it is). This is not the case, as shown by the following:

Object o = "Hello";
mutate(o)
System.out.println(o);

private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!

Will print Hello to the console. The options if you wanted the above code to print Goodbye are to use an explicit reference as follows:

AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!

private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }
oxbow_lakes
Also, an array of length 1 can be used to create a reference if you really want to confuse people :)
Christoffer
This is very true
oxbow_lakes
+4  A: 

I don't think you can. Your best option might be to encapsulate the thing you want to pass "by ref" onto another class instance, and pass the (outer) class's reference (by value). If you see what I mean...

i.e. your method changes the internal state of the object it is passed, which is then visible to the caller.

Marc Gravell
+5  A: 

In Java there is nothing at language level similar to ref. In Java there is only passing by value semantic

For the sake of curiosity you can implement a ref-like semantic in Java simply wrapping your objects in a mutable class:

public class Ref<T> {

    private T value;

    public Ref(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

    public void set(T anotherValue) {
        value = anotherValue;
    }

    @Override
    public String toString() {
        return value.toString();
    }

    @Override
    public boolean equals(Object obj) {
        return value.equals(obj);
    }

    @Override
    public int hashCode() {
        return value.hashCode();
    }
}

testcase:

public void changeRef(Ref<String> ref) {
    ref.set("bbb");
}

// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"
dfa
Should the second to last line read "test(ref);"?
Brian Fisher
@Brian Fisher: fixed, thanks
dfa
Why not use java.lang.ref.Reference instead?
Hardcoded
java.lang.ref.Reference don't have a set method, it is not mutable
dfa
+7  A: 
PeterMmm
+1 for nerdness!
dfa
A: 

Java is always pass by value.

When you pass a primitive it's a copy of the value, when you pass an object it's a copy of the reference pointer.

Nick Holt
A: 

See my article, "Java is Pass-By-Value, Dammit!" for a very detailed explanation of how Java passes parameters.

http://javadude.com/articles/passbyvalue.htm

Scott Stanchfield
+2  A: 

From James Gosling in "The Java Programming Language":

"...There is exactly one parameter passing mode in Java - pass by value - and that keeps things simple. .."

duffymo