'How to do the equivalent of pass by reference for primitives in Java
This Java code:
public class XYZ {
public static void main(){
int toyNumber = 5;
XYZ temp = new XYZ();
temp.play(toyNumber);
System.out.println("Toy number in main " + toyNumber);
}
void play(int toyNumber){
System.out.println("Toy number in play " + toyNumber);
toyNumber++;
System.out.println("Toy number in play after increement " + toyNumber);
}
}
will output this:
Toy number in play 5 Toy number in play after increement 6 Toy number in main 5
In C++ I can pass the toyNumber
variable as pass by reference to avoid shadowing i.e. creating a copy of the same variable as below:
void main(){
int toyNumber = 5;
play(toyNumber);
cout << "Toy number in main " << toyNumber << endl;
}
void play(int &toyNumber){
cout << "Toy number in play " << toyNumber << endl;
toyNumber++;
cout << "Toy number in play after increement " << toyNumber << endl;
}
and the C++ output will be this:
Toy number in play 5 Toy number in play after increement 6 Toy number in main 6
My question is - What's the equivalent code in Java to get the same output as the C++ code, given that Java is pass by value rather than pass by reference?
Solution 1:[1]
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]);
}
Solution 2:[2]
Java is not call by reference it is call by value only
But all variables of object type are actually pointers.
So if you use a Mutable Object you will see the behavior you want
public class XYZ {
public static void main(String[] arg) {
StringBuilder toyNumber = new StringBuilder("5");
play(toyNumber);
System.out.println("Toy number in main " + toyNumber);
}
private static void play(StringBuilder toyNumber) {
System.out.println("Toy number in play " + toyNumber);
toyNumber.append(" + 1");
System.out.println("Toy number in play after increement " + toyNumber);
}
}
Output of this code:
run:
Toy number in play 5
Toy number in play after increement 5 + 1
Toy number in main 5 + 1
BUILD SUCCESSFUL (total time: 0 seconds)
You can see this behavior in Standard libraries too. For example Collections.sort(); Collections.shuffle(); These methods does not return a new list but modifies it's argument object.
List<Integer> mutableList = new ArrayList<Integer>();
mutableList.add(1);
mutableList.add(2);
mutableList.add(3);
mutableList.add(4);
mutableList.add(5);
System.out.println(mutableList);
Collections.shuffle(mutableList);
System.out.println(mutableList);
Collections.sort(mutableList);
System.out.println(mutableList);
Output of this code:
run:
[1, 2, 3, 4, 5]
[3, 4, 1, 5, 2]
[1, 2, 3, 4, 5]
BUILD SUCCESSFUL (total time: 0 seconds)
Solution 3:[3]
Make a
class PassMeByRef { public int theValue; }
then pass a reference to an instance of it. Note that a method that mutates state through its arguments is best avoided, especially in parallel code.
Solution 4:[4]
For a quick solution, you can use AtomicInteger or any of the atomic variables which will let you change the value inside the method using the inbuilt methods. Here is sample code:
import java.util.concurrent.atomic.AtomicInteger;
public class PrimitivePassByReferenceSample {
/**
* @param args
*/
public static void main(String[] args) {
AtomicInteger myNumber = new AtomicInteger(0);
System.out.println("MyNumber before method Call:" + myNumber.get());
PrimitivePassByReferenceSample temp = new PrimitivePassByReferenceSample() ;
temp.changeMyNumber(myNumber);
System.out.println("MyNumber After method Call:" + myNumber.get());
}
void changeMyNumber(AtomicInteger myNumber) {
myNumber.getAndSet(100);
}
}
Output:
MyNumber before method Call:0
MyNumber After method Call:100
Solution 5:[5]
You cannot pass primitives by reference in Java. All variables of object type are actually pointers, of course, but we call them "references", and they are also always passed by value.
In a situation where you really need to pass a primitive by reference, what people will do sometimes is declare the parameter as an array of primitive type, and then pass a single-element array as the argument. So you pass a reference int[1], and in the method, you can change the contents of the array.
Solution 6:[6]
public static void main(String[] args) {
int[] toyNumber = new int[] {5};
NewClass temp = new NewClass();
temp.play(toyNumber);
System.out.println("Toy number in main " + toyNumber[0]);
}
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]);
}
Solution 7:[7]
"Pass-by..." is reserved in Java and C. Beyond this, if you intend to change a wrapper instance of a primitive given as reference, this is done by reflection. Example for Integer
.
public class WrapperTest
{
static void mute(Integer a)
{
try
{
Field fValue = a.getClass().getDeclaredField("value");
fValue.setAccessible(true);
fValue.set(a, 6);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
Integer z = 5;
mute(z);
System.out.println(z);
}
}
Output is 6 as in your C++ example. Reflection is required, because Java design considers primitive wrappers as immutable. Else every other class can serve as wrapper, even an array like int[]
of length 1 .
Solution 8:[8]
We set a = 5 in the checkPassByValue but it is not reflected in the value of a. Similarly, when we pass a person we can update the data where the person points to by using Person.setName however if change the person and make it refer to a new Person() in that case that update will not be reflected in the main function
class Person {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
public Person(String name) {
this.name = name;
}
}
public class PassByValueVsReference {
public static void main(String[] args) {
int a = 3;
Person person = new Person("Foo");
checkPassByValue(a, person);
System.out.println(a);
System.out.println(person.getName());
}
public static void checkPassByValue(int number, Person person) {
number = 5;
person.setName("Foo-updated");
person = new Person("Foo_new reference");
}
}
//C++ equivalent of checkPassByValue(int ,Person *);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | |
Solution 4 | Lucas Zamboulis |
Solution 5 | |
Solution 6 | itun |
Solution 7 | |
Solution 8 |