How do I pass a primitive data type by reference?

37,393

Solution 1

There isn't a way to pass a primitive directly by reference in Java.

A workaround is to instead pass a reference to an instance of a wrapper class, which then contains the primitive as a member field. Such a wrapper class could be extremely simple to write for yourself:

public class IntRef { public int value; }

But how about some pre-built wrapper classes, so we don't have to write our own? OK:

The Apache commons-lang Mutable* classes:
Advantages: Good performance for single threaded use. Completeness.
Disadvantages: Introduces a third-party library dependency. No built-in concurrency controls.
Representative classes: MutableBoolean, MutableByte, MutableDouble, MutableFloat, MutableInt, MutableLong, MutableObject, MutableShort.

The java.util.concurrent.atomic Atomic* classes:
Advantages: Part of the standard Java (1.5+) API. Built-in concurrency controls.
Disadvantages: Small performance hit when used in a single-threaded setting. Missing direct support for some datatypes, e.g. there is no AtomicShort.
Representative classes: AtomicBoolean, AtomicInteger, AtomicLong, and AtomicReference.
Note: As user ColinD shows in his answer, AtomicReference can be used to approximate some of the missing classes, e.g. AtomicShort.

Length 1 primitive array
OscarRyz's answer demonstrates using a length 1 array to "wrap" a primitive value.
Advantages: Quick to write. Performant. No 3rd party library necessary.
Disadvantages: A little dirty. No built-in concurrency controls. Results in code that does not (clearly) self-document: is the array in the method signature there so I can pass multiple values? Or is it here as scaffolding for pass-by-reference emulation?

Also see
The answers to StackOverflow question "Mutable boolean field in Java".

My Opinion
In Java, you should strive to use the above approaches sparingly or not at all. In C it is common to use a function's return value to relay a status code (SUCCESS/FAILURE), while a function's actual output is relayed via one or more out-parameters. In Java, it is best to use Exceptions instead of return codes. This frees up method return values to be used for carrying the actual method output -- a design pattern which most Java programmers find to be more natural than out-parameters.

Solution 2

Nothing in java is passed by reference. It's all passed by value.

Edit: Both primitives and object types are passed by value. You can never alter the passed value/reference and expect the originating value/reference to change. Example:

String a;
int b;

doSomething(a, b);

...

public void doSomething(String myA, int myB) {
   // whatever I do to "myA" and "myB" here will never ever ever change
   // the "a" and "b"
}

The only way to get around this hurdle, regardless of it being a primitive or reference, is to pass a container object, or use the return value.

With a holder:

private class MyStringHolder {
  String a;
  MyStringHolder(String a) {
    this.a = a;
  }
}

MyStringHolder holdA = new MyStringHolder("something");

public void doSomething(MyStringHolder holder) {
   // alter holder.a here and it changes.
}

With return value

int b = 42;
b = doSomething(b);

public int doSomething(int b) {
  return b + 1;
}

Solution 3

Pass an AtomicInteger, AtomicBoolean, etc. instead. There isn't one for every primitive type, but you can use, say, an AtomicReference<Short> if necessary too.

Do note: there should very rarely be a need to do something like this in Java. When you want to do it, I'd recommend rethinking what you're trying to do and seeing if you can't do it some other way (using a method that returns an int, say... what exactly the best thing to do is will vary from situation to situation).

Solution 4

That's not possible in Java, as an alternative you can wrap it in a single element array.

void demo() { 
    int [] a = { 0 };
    increment ( a ) 
}
void increment( int [] v ) { 
     v[0]++;
}

But there are always better options.

Solution 5

You can't. But you can return an integer which is a modified value

int i = 0;
i = doSomething(i);

If you are passing in more than one you may wish to create a Data Transfer Object (a class specifically to contain a set of variables which can be passed to classes).

Share:
37,393
Neuquino
Author by

Neuquino

SOreadytohelp just ask me what you want to know

Updated on June 25, 2020

Comments

  • Neuquino
    Neuquino almost 4 years

    How can I pass a primitive type by reference in java? For instance, how do I make an int passed to a method modifiable?

  • Laurence Gonsalves
    Laurence Gonsalves over 13 years
    java.lang.Integer and friends are immutable. java.util.concurrent.atomic.AtomicInteger and friends are mutable. Another (kind of gross) option I've seen is to use a 1-element array.
  • Tim Bender
    Tim Bender over 13 years
    +1 though I think this might be heavy handed as compared to just using a wrapper/holder object.
  • ColinD
    ColinD over 13 years
    If you just use set(int) to mutate it, I don't think there would be any performance impact worth worrying about... creating your own mutable wrapper to do this (or importing commons-lang, for that matter...) would be a far worse offense in my opinion. Also, I hope this isn't being done very often, as I don't think there are many cases where this is really needed.
  • Tim Bender
    Tim Bender over 13 years
    Agree on importing commons-lang being a bad idea. I'm guessing the OP is a C programmer and that he wants to keep using the same paradigms which lead to most of the complexities in understanding a C program, so I imagine he will be using this "pass primitive by reference" solution quite frequently.
  • Bugmaster
    Bugmaster over 13 years
    I agree; passing mutable primitives, C-style, is almost always the wrong thing to do in Java. All it does is make the code needlessly complicated.
  • tchrist
    tchrist over 13 years
    “Correct” is a boolean condition, and does not admit modifiers of degree or kind.
  • ColinD
    ColinD over 13 years
    @tchrist: You can make a correct statement without actually answering a question. I can say "1 + 1 = 2", which is correct but does not answer the question. The original answer here was closer to answering the question than that, but still did not provide any kind of answer that would actually be useful to the asker.
  • Nyerguds
    Nyerguds almost 11 years
    Atomics are very handy to pass a counter to a function that's called multiple times, though, especially if the increase of the counter is conditional in the function, but not increasing it doesn't necessarily means something failed. Anyway, thanks for this answer. It's very helpful.
  • B.B.
    B.B. over 7 years
    This is one way of achieving it, for a single value!