javapass-by-referenceprimitive-types

How do I pass a primitive data type by reference?


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


Solution

  • 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.