How to Do the Equivalent of Pass by Reference for Primitives in Java

How to do the equivalent of pass by reference for primitives in Java

You have several choices. The one that makes the most sense really depends on what you're trying to do.

Choice 1: make toyNumber a public member variable in a class

class MyToy {
public int toyNumber;
}

then pass a reference to a MyToy to your method.

void play(MyToy toy){  
System.out.println("Toy number in play " + toy.toyNumber);
toy.toyNumber++;
System.out.println("Toy number in play after increement " + toy.toyNumber);
}

Choice 2: return the value instead of pass by reference

int play(int toyNumber){  
System.out.println("Toy number in play " + toyNumber);
toyNumber++;
System.out.println("Toy number in play after increement " + toyNumber);
return toyNumber
}

This choice would require a small change to the callsite in main so that it reads, toyNumber = temp.play(toyNumber);.

Choice 3: make it a class or static variable

If the two functions are methods on the same class or class instance, you could convert toyNumber into a class member variable.

Choice 4: Create a single element array of type int and pass that

This is considered a hack, but is sometimes employed to return values from inline class invocations.

void play(int [] toyNumber){  
System.out.println("Toy number in play " + toyNumber[0]);
toyNumber[0]++;
System.out.println("Toy number in play after increement " + toyNumber[0]);
}

Passing primitive data by reference in Java

In Java, it is not possible to pass primitives by reference. To emulate this, you must pass a reference to an instance of a mutable wrapper class.

See How do I pass a primitive data type by reference? for more info on mutable wrapper classes.

How do I pass a primitive data type by reference?

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.

Can I pass a primitive type by reference in Java?

While Java supports overloading, all parameters are passed by value, i.e. assigning a method argument is not visible to the caller.

From your code snippet, you are trying to return a value of different types. Since return types are not part of a method's signature, you can not overload with different return types. Therefore, the usual approach is:

int getIntValue() { ... }
byte getByteValue() { ... }

If this is actually a conversion, the standard naming is

int toInt() { ...}
byte toByte() { ... }

JAVA Pass Primitive type as a Reference to function call

Are you aware of java streams? With streams you can do something like:

List<Object> result = objects.stream()
.filter(object -> {/*add condition here*/})
.map(object->{/*do something with object that match condition above*/})
.collect(Collectors.toList());

You can use this mechanism to collect and process objects based on certain conditions.

If that doesn't help, maybe use an iterator?

Iterator<Object> it = objects.iterator();
while(it.hasNext()){
Object node = someFunction(session,it);
}

public Object someFunction(Session session,Iterator i){
//manipulate i value based on condition
if(true){
i.next();
}else{
i.next();
i.next();
}
}

java pass by value primitive vs objects

You pass the reference of the BirthDate by value, so your method refers to the same BirthDate as in your main method.

However you then change the member of that object (lear) from 200 to 400.

Because you've passed the reference to the original object, it's not been copied and you're dealing with the same object at all times.

A reference to primitive type in Java (How to force a primitive data to remain boxed)

Integer is immutable, as you may notice.

Your approach with private static class IntegerWrapper is correct one. Using array with size 1 is also correct, but in practice I have never seen using array for this case. So do use IntegerWrapper.

Exactly the same implementation you can find in Apache org.apache.commons.lang3.mutable.MutableInt.

In your example you also can provide Main instance to the static method:

public class Main {

private int x = 42;

public static void main(String[] args) {
Main main = new Main();
incrementX(main);
}

private static void incrementX(Main main) {
main.x++;
}
}

And finally, from Java8 you could define an inc function and use it to increment value:

public class Main {

private static final IntFunction<Integer> INC = val -> val + 1;

private int x = 42;

public static void main(String[] args) {
Main main = new Main();
main.x = INC.apply(main.x);
}

}


Related Topics



Leave a reply



Submit