141

Something like the following:

ref example:

void changeString(ref String str) {
    str = "def";
}

void main() {
    String abc = "abc";
    changeString(ref abc);
    System.out.println(abc); //prints "def"
}

out example:

void changeString(out String str) {
    str = "def";
}

void main() {
    String abc;
    changeString(out abc);
    System.out.println(abc); //prints "def"
}
Yair Kukielka
  • 10,686
  • 1
  • 38
  • 46
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • 1
    possible duplicate of [Can I pass parameters by reference in Java?](http://stackoverflow.com/questions/1068760/can-i-pass-parameters-by-reference-in-java) – Robert Harvey May 10 '10 at 21:24
  • 5
    IMO you're not missing much. The only time I ever use `ref` or `out` in C# is when I am using a pattern like `TryParse()`, where the method returns a boolean result, and the only way to get a parsed value out of it is by using `ref` or `out`. – Robert Harvey May 10 '10 at 21:40
  • 4
    Guess what, that is right what I need to use! ;) – devoured elysium May 10 '10 at 21:44
  • 1
    The other way to do it is to return a composite object with both the status and a nullable value in it. But I admit that's a bit Rube Goldberg-ish. – Robert Harvey May 10 '10 at 21:46
  • 1
    Nothing wrong with returning a composite object, if only there would be a predefined usable one (i.e. tuples). But wait, that'd need non-erased generics working with primitive types to be efficient :) – Pavel Minaev May 10 '10 at 22:35
  • I think returning a value if successful and throwing an exception if not is the usual way it's done in Java. – Skip Head May 11 '10 at 03:12
  • in c# ref and out is something we should avoid – Sean Dec 04 '15 at 14:45
  • @Sean Why? If you have a routine that needs to return for example two integers then using out parameters is perfectly acceptable. – Karlth Jun 20 '21 at 00:20
  • @Karlth you have lots of options to return two integers from a method, and out parameters is definitely not a good option – Sean Jun 20 '21 at 04:17
  • @Sean What options? The only possibility I see is to make a seperate class for the values and returning that which is a lot of red tape for a simple functionality. Any other options? – Karlth Jun 20 '21 at 17:39
  • @Karlth IMO, use tuple or record type is a better option to return mulitple value – Sean Jun 21 '21 at 04:02

7 Answers7

125

No, Java doesn't have something like C#'s ref and out keywords for passing by reference.

You can only pass by value in Java. Even references are passed by value. See Jon Skeet's page about parameter passing in Java for more details.

To do something similar to ref or out you would have to wrap your parameters inside another object and pass that object reference in as a parameter.

Joe White
  • 94,807
  • 60
  • 220
  • 330
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • And there's nothing like out? – devoured elysium May 10 '10 at 21:26
  • 5
    This should be expanded on some. You can only pass primitives (int, short, char, etc.) as value. And no, there is no out. – Corey Sunwold May 10 '10 at 21:26
  • 18
    That is not 100% true, If you pass in an array or a class the reference to the array or object is passed in by value, You can change internals to the array or object and it will be reflected in the caller. – Romain Hippeau May 10 '10 at 21:27
  • 1
    you can only pass by value in C# too. That doesn't answer the question though. – fearofawhackplanet May 10 '10 at 21:37
  • 13
    @fearofawhackplanet: Um, unless you use `ref`. – Robert Harvey May 10 '10 at 21:41
  • 1
    @robert: references are passed by value in both c# and java. *All* parameters (including `ref`) are passed by value in c#. It is completely irrelevant to the question. – fearofawhackplanet May 10 '10 at 21:59
  • 2
    @fearofawhackplanet: `Reference parameters need the ref modifier as part of both the declaration and the invocation - that means it's always clear when you're passing something by reference.` http://www.yoda.arachsys.com/csharp/parameters.html – Mark Byers May 10 '10 at 22:03
  • 5
    From CLR perspective, you're passing a managed reference (`T&`) by value, yes. But C# has its own terminology, and it specifically doesn't include such things as values of type `ref T` - from C# perspective, `ref` is strictly a parameter modifier, and speaking of "passing a reference by value" with respect to it doesn't make sense. – Pavel Minaev May 10 '10 at 22:36
  • 1
    From an assembler perspective, when you call a function with an object variable, you make a local int variable and put the memory address of that object in it. Any changes you make to that object's properties are done in the original memory of the object, but if you reassign the local variable to a new object, you're not replacing the old object, but rather the stored reference; all that does is remove the reference you needed. Java has the `atomic` toolset's wrapper classes to pass stuff by reference though. – Nyerguds Jun 29 '11 at 06:48
  • how about final keyword in JAVA? `void CannotChangeString(final String str) {...}` – Tohid Aug 04 '17 at 17:26
  • Objects are not passed my value!! – themhz Jun 12 '20 at 08:22
32

Direct answer: No

But you can simulate reference with wrappers.

And do the following:

void changeString( _<String> str ) {
    str.s("def");
}

void testRef() {
     _<String> abc = new _<String>("abc");
     changeString( abc );
     out.println( abc ); // prints def
}

Out

void setString( _<String> ref ) {
    str.s( "def" );
}
void testOut(){
    _<String> abc = _<String>();
    setString( abc );
    out.println(abc); // prints def
}

And basically any other type such as:

_<Integer> one = new <Integer>(1);
addOneTo( one );

out.println( one ); // May print 2
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • 47
    I never said, *You can do it in this elegant way* :P – OscarRyz May 11 '10 at 14:57
  • so why does the following not work: private static void ParseLine(String newline, String[] aWrapper, Integer[] bWrapper) { StringTokenizer st = new StringTokenizer(newline); aWrapper[0] = st.nextToken(); bWrapper[0]= new Integer(st.nextToken()); } ParseLine(newline, new String[] {a}, new Integer[] {b}); – Elad Benda Dec 31 '10 at 09:37
  • That is nasty, but I am still giving this a like because it does solve the problem in a "cleanest" way that I can think of for Java at this moment in time... – Pangamma Dec 23 '18 at 01:07
  • Why would you introduce a new class `_` for this while there is already a similar class `AtomicReference` in the base class library? – Dennie Mar 01 '21 at 08:52
9

Java passes parameters by value and doesn't have any mechanism to allow pass-by-reference. That means that whenever a parameter is passed, its value is copied into the stack frame handling the call.

The term value as I use it here needs a little clarification. In Java we have two kinds of variables - primitives and objects. A value of a primitive is the primitive itself, and the value of an object is its reference (and not the state of the object being referenced). Therefore, any change to the value inside the method will only change the copy of the value in the stack, and will not be seen by the caller. For example, there isn't any way to implement a real swap method, that receives two references and swaps them (not their content!).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eyal Schneider
  • 22,166
  • 5
  • 47
  • 78
9

Actually there is neither ref nor out keyword equivalent in Java language as far as I know. However I've just transformed a C# code into Java that uses out parameter and will advise what I've just done. You should wrap whatever object into a wrapper class and pass the values wrapped in wrapper object instance as follows;

A Simple Example For Using Wrapper

Here is the Wrapper Class;

public class Wrapper {
    public Object ref1; // use this as ref
    public Object ref2; // use this as out

    public Wrapper(Object ref1) {
        this.ref1 = ref1;
    }
}

And here is the test code;

public class Test {

    public static void main(String[] args) {
        String abc = "abc";
        changeString(abc);
        System.out.println("Initial object: " + abc); //wont print "def"

        Wrapper w = new Wrapper(abc);
        changeStringWithWrapper(w);
        System.out.println("Updated object: " + w.ref1);
        System.out.println("Out     object: " + w.ref2);
    }

    // This won't work
    public static void changeString(String str) {
        str = "def";
    }

    // This will work
    public static void changeStringWithWrapper(Wrapper w) {
        w.ref1 = "def";
        w.ref2 = "And this should be used as out!";
    }

}

A Real World Example

A C#.NET method using out parameter

Here there is a C#.NET method that is using out keyword;

public bool Contains(T value)
{
    BinaryTreeNode<T> parent;
    return FindWithParent(value, out parent) != null;
}

private BinaryTreeNode<T> FindWithParent(T value, out BinaryTreeNode<T> parent)
{
    BinaryTreeNode<T> current = _head;
    parent = null;

    while(current != null)
    {
        int result = current.CompareTo(value);

        if (result > 0)
        {
            parent = current;
            current = current.Left;
        }
        else if (result < 0)
        {
            parent = current;
            current = current.Right;
        }
        else
        {
            break;
        }
    }

    return current;
}

Java Equivalent of the C# code that is using the out parameter

And the Java equivalent of this method with the help of wrapper class is as follows;

public boolean contains(T value) {
    BinaryTreeNodeGeneration<T> result = findWithParent(value);

    return (result != null);
}

private BinaryTreeNodeGeneration<T> findWithParent(T value) {
    BinaryTreeNode<T> current = head;
    BinaryTreeNode<T> parent = null;
    BinaryTreeNodeGeneration<T> resultGeneration = new BinaryTreeNodeGeneration<T>();
    resultGeneration.setParentNode(null);

    while(current != null) {
        int result = current.compareTo(value);

        if(result >0) {
            parent = current;
            current = current.left;
        } else if(result < 0) {
            parent = current;
            current = current.right;
        } else {
            break;
        }
    }

    resultGeneration.setChildNode(current);
    resultGeneration.setParentNode(parent);

    return resultGeneration;
}

Wrapper Class

And the wrapper class used in this Java code is as below;

public class BinaryTreeNodeGeneration<TNode extends Comparable<TNode>>  {

    private BinaryTreeNode<TNode>   parentNode;
    private BinaryTreeNode<TNode>   childNode;

    public BinaryTreeNodeGeneration() {
        this.parentNode = null;
        this.childNode = null;
    }

    public BinaryTreeNode<TNode> getParentNode() {
        return parentNode;
    }

    public void setParentNode(BinaryTreeNode<TNode> parentNode) {
        this.parentNode = parentNode;
    }

    public BinaryTreeNode<TNode> getChildNode() {
        return childNode;
    }

    public void setChildNode(BinaryTreeNode<TNode> childNode) {
        this.childNode = childNode;
    }

}
Levent Divilioglu
  • 11,198
  • 5
  • 59
  • 106
  • see former answers. – pashute Sep 18 '17 at 05:11
  • Giving a detailed answer a negative vote is funny. I've checked out SO and couldn't find a fine exact answer with demo code, that's why I've written this answer as far as I can remember. If you wait for a single answer and down vote every other answer, then SO should ban all the answer other than that got a confirmation from the owner of the question. – Levent Divilioglu Sep 18 '17 at 13:58
  • OK, I can remove the negative vote only if you edit the answer. So read the other answers and explain why you didn't want to use those solutions. A wrapper (and in particular a REF and OUT wrapper just for the fun of it). 5 people gave short and full answers __with examples__, and only Eyal basically wrote: "No you can't". – pashute Sep 19 '17 at 16:09
  • 1
    This answer looks fine. It is similar to the top answer, but gives fully detailed examples on how to use a wrapper class in Java. – hubatish Aug 10 '18 at 16:44
6

Like many others, I needed to convert a C# project to Java. I did not find a complete solution on the web regarding out and ref modifiers. But, I was able to take the information I found, and expand upon it to create my own classes to fulfill the requirements. I wanted to make a distinction between ref and out parameters for code clarity. With the below classes, it is possible. May this information save others time and effort.

An example is included in the code below.

//*******************************************************************************************
//XOUT CLASS
//*******************************************************************************************
public class XOUT<T>
{
    public XOBJ<T> Obj = null;

    public XOUT(T value)
    {
        Obj = new XOBJ<T>(value);
    }

    public XOUT()
    {
      Obj = new XOBJ<T>();
    }

    public XOUT<T> Out()
    {
        return(this);
    }

    public XREF<T> Ref()
    {
        return(Obj.Ref());
    }
};

//*******************************************************************************************
//XREF CLASS
//*******************************************************************************************

public class XREF<T>
{
    public XOBJ<T> Obj = null;

    public XREF(T value)
    {
        Obj = new XOBJ<T>(value);
    }

    public XREF()
    {
      Obj = new XOBJ<T>();
    }

    public XOUT<T> Out()
    {
        return(Obj.Out());
    }

    public XREF<T> Ref()
    {
        return(this);
    }
};

//*******************************************************************************************
//XOBJ CLASS
//*******************************************************************************************
/**
 *
 * @author jsimms
 */
/*
    XOBJ is the base object that houses the value. XREF and XOUT are classes that
    internally use XOBJ. The classes XOBJ, XREF, and XOUT have methods that allow
    the object to be used as XREF or XOUT parameter; This is important, because
    objects of these types are interchangeable.

    See Method:
       XXX.Ref()
       XXX.Out()

    The below example shows how to use XOBJ, XREF, and XOUT;
    //
    // Reference parameter example
    //
    void AddToTotal(int a, XREF<Integer> Total)
    {
       Total.Obj.Value += a;
    }

    //
    // out parameter example
    //
    void Add(int a, int b, XOUT<Integer> ParmOut)
    {
       ParmOut.Obj.Value = a+b;
    }

    //
    // XOBJ example
    //
    int XObjTest()
    {
       XOBJ<Integer> Total = new XOBJ<>(0);
       Add(1, 2, Total.Out());    // Example of using out parameter
       AddToTotal(1,Total.Ref()); // Example of using ref parameter
       return(Total.Value);
    }
*/


public class XOBJ<T> {

    public T Value;

    public  XOBJ() {

    }

    public XOBJ(T value) {
        this.Value = value;
    }

    //
    // Method: Ref()
    // Purpose: returns a Reference Parameter object using the XOBJ value
    //
    public XREF<T> Ref()
    {
        XREF<T> ref = new XREF<T>();
        ref.Obj = this;
        return(ref);
    }

    //
    // Method: Out()
    // Purpose: returns an Out Parameter Object using the XOBJ value
    //
    public XOUT<T> Out()
    {
        XOUT<T> out = new XOUT<T>();
        out.Obj = this;
        return(out);
    }

    //
    // Method get()
    // Purpose: returns the value
    // Note: Because this is combersome to edit in the code,
    // the Value object has been made public
    //
    public T get() {
        return Value;
    }

    //
    // Method get()
    // Purpose: sets the value
    // Note: Because this is combersome to edit in the code,
    // the Value object has been made public
    //
    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();
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
James W Simms
  • 841
  • 1
  • 8
  • 9
2

Three solutions not officially, explicitly mentioned:

ArrayList<String> doThings() {
  //
}

void doThings(ArrayList<String> list) {
  //
}

Pair<String, String> doThings() {
  //
}

For Pair, I would recommend: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html

Andrew
  • 5,839
  • 1
  • 51
  • 72
-1

java has no standard way of doing it. Most swaps will be made on the list that is packaged in the class. but there is an unofficial way to do it:

package Example;

import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;



 public class Test{


private static <T> void SetValue(T obj,T value){
    try {
        Field f = obj.getClass().getDeclaredField("value");
        f.setAccessible(true);
        f.set(obj,value);
        } catch (IllegalAccessException | IllegalArgumentException | 
            NoSuchFieldException | SecurityException ex) {
            Logger.getLogger(CautrucjavaCanBan.class.getName()).log(Level.SEVERE, 
       null, ex);
        }
}
private  static  void permutation(Integer a,Integer b){
    Integer tmp = new Integer(a);
    SetValue(a, b);
    SetValue(b, tmp);
}
 private  static  void permutation(String a,String b){
    char[] tmp = a.toCharArray();
    SetValue(a, b.toCharArray());
    SetValue(b, tmp);
}
public static void main(String[] args) {
    {
        Integer d = 9;
        Integer e = 8;
        HoanVi(d, e);
        System.out.println(d+" "+ e);
    }
    {
        String d = "tai nguyen";
        String e = "Thai nguyen";
        permutation(d, e);
        System.out.println(d+" "+ e);
    }
}

}
  • 2
    That's not giving you reference semantics for a parameter, that's just using reflection to mutate an object that's designed to be immutable, which is a *terrible* idea, and still doesn't provide reference semantics for the parameter. – Servy Sep 05 '18 at 19:47