There are two problems:
- Java uses pass by value, not by reference. Changing the reference inside a method won't be reflected into the passed-in reference in the calling method.
- Integer is immutable. There's no such method like
Integer#set(i). You could otherwise just make use of it.
To get it to work, you need to reassign the return value of the inc() method.
integer = inc(integer);
To learn a bit more about passing by value, here's another example:
public static void main(String... args) {
String[] strings = new String[] { "foo", "bar" };
changeReference(strings);
System.out.println(Arrays.toString(strings)); // still [foo, bar]
changeValue(strings);
System.out.println(Arrays.toString(strings)); // [foo, foo]
}
public static void changeReference(String[] strings) {
strings = new String[] { "foo", "foo" };
}
public static void changeValue(String[] strings) {
strings[1] = "foo";
}
Answer from BalusC on Stack OverflowThere are two problems:
- Java uses pass by value, not by reference. Changing the reference inside a method won't be reflected into the passed-in reference in the calling method.
- Integer is immutable. There's no such method like
Integer#set(i). You could otherwise just make use of it.
To get it to work, you need to reassign the return value of the inc() method.
integer = inc(integer);
To learn a bit more about passing by value, here's another example:
public static void main(String... args) {
String[] strings = new String[] { "foo", "bar" };
changeReference(strings);
System.out.println(Arrays.toString(strings)); // still [foo, bar]
changeValue(strings);
System.out.println(Arrays.toString(strings)); // [foo, foo]
}
public static void changeReference(String[] strings) {
strings = new String[] { "foo", "foo" };
}
public static void changeValue(String[] strings) {
strings[1] = "foo";
}
Good answers above explaining the actual question from the OP.
If anyone needs to pass around a number that needs to be globally updated, use the AtomicInteger() instead of creating the various wrapper classes suggested or relying on 3rd party libs.
The AtomicInteger() is of course mostly used for thread safe access but if the performance hit is no issue, why not use this built-in class. The added bonus is of course the obvious thread safety.
import java.util.concurrent.atomic.AtomicInteger
You can try using org.apache.commons.lang.mutable.MutableInt from Apache Commons library. There is no direct way of doing this in the language itself.
This isn't possible in Java. As you've suggested one way is to pass an int[]. Another would be do have a little class e.g. IntHolder that wrapped an int.
java Integer reference - Stack Overflow
Why does java not have pass by reference
How to do the equivalent of pass by reference for primitives in Java - Stack Overflow
methods - Is Java "pass-by-reference" or "pass-by-value"? - Stack Overflow
Videos
Most of the classes such as Integer that derive from Java's abstract Number class are immutable., i.e. once constructed, they can only ever contain that particular number.
A useful benefit of this is that it permits caching. If you call:
Integer i = Integer.valueOf(n);
for -128 <= n < 127 instead of:
Integer i = Integer.new(n)
you get back a cached object, rather than a new object. This saves memory and increases performance.
In the latter test case with a bare int argument, all you're seeing is how Java's variables are passed by value rather than by reference.
@Alnitak -> correct. And to add what really happens here. The ++i due to autoboxing works like that:
int val = Integer.intValue(); ++val;
and val is not stored anywhere, thus increment is lost.
In c#, you can use the keyword ref to pass a primitive by reference, which sometimes comes in handy. Why does java not have this? It forces you to either use a hack (like 1 length array), refactor code, or return multiple values via your own Tuple class.
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]);
}
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)
I have created a question devoted to these kind of questions for any programming languages here.
Java is also mentioned. Here is the short summary:
- Java passes it parameters by value
- "by value" is the only way in Java to pass a parameter to a method
- using methods from the object given as parameter will alter the object as the references point to the original objects (if that method itself alters some values).
One of the biggest confusions in the Java programming language is whether Java is pass by value or pass by reference.
First of all, we should understand what is meant by pass by value or pass by reference.
Pass by value: The method parameter values are copied to another variable and then the copied object is passed. That’s why it’s called pass by value.
Pass by reference: An alias or reference to the actual parameter is passed to the method. That’s why it’s called pass by reference.
Let’s say we have a class, Balloon, like below.
public class Balloon {
private String color;
public Balloon(){}
public Balloon(String c){
this.color=c;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
And we have a simple program with a generic method to swap two objects. The class looks like below.
public class Test {
public static void main(String[] args) {
Balloon red = new Balloon("Red"); // Memory reference 50
Balloon blue = new Balloon("Blue"); // Memory reference 100
swap(red, blue);
System.out.println("red color="+red.getColor());
System.out.println("blue color="+blue.getColor());
foo(blue);
System.out.println("blue color="+blue.getColor());
}
private static void foo(Balloon balloon) { // baloon=100
balloon.setColor("Red"); // baloon=100
balloon = new Balloon("Green"); // baloon=200
balloon.setColor("Blue"); // baloon = 200
}
// Generic swap method
public static void swap(Object o1, Object o2){
Object temp = o1;
o1 = o2;
o2 = temp;
}
}
When we execute the above program, we get following output.
red color=Red
blue color=Blue
blue color=Red
If you look at the first two lines of the output, it’s clear that swap method didn’t work. This is because Java is passed by value; this swap() method test can be used with any programming language to check whether it’s passed by value or passed by reference.
Let’s analyze the program execution step by step.
Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");
When we use the new operator to create an instance of a class, the instance is created and the variable contains the reference location of the memory where the object is saved. For our example, let’s assume that “red” is pointing to 50 and “blue” is pointing to 100, and these are the memory location of both Balloon objects.
Now when we are calling the swap() method, two new variables o1 and o2 are created, pointing to 50 and 100, respectively.
So the below code snippet explains what happened in the swap() method execution.
public static void swap(Object o1, Object o2){ // o1=50, o2=100
Object temp = o1; // temp=50, o1=50, o2=100
o1 = o2; // temp=50, o1=100, o2=100
o2 = temp; // temp=50, o1=100, o2=50
} // Method terminated
Notice that we are changing the values of o1 and o2, but they are copies of “red” and “blue” reference locations, so actually, there isn't any change in the values of “red” and “blue” and hence the output.
If you have understood this far, you can easily understand the cause of the confusion. Since the variables are just the references to the objects, we get confused that we are passing the reference, so Java is passed by reference. However, we are passing a copy of the reference and hence it’s passed by value. I hope it clears all the questions now.
Now let’s analyze the foo() method execution.
private static void foo(Balloon balloon) { // baloon=100
balloon.setColor("Red"); // baloon=100
balloon = new Balloon("Green"); // baloon=200
balloon.setColor("Blue"); // baloon = 200
}
The first line is the important one. When we call a method, the method is called on the Object at the reference location. At this point, the balloon is pointing to 100 and hence it’s color is changed to Red.
In the next line, the balloon reference is changed to 200 and any further methods executed are happening on the object at memory location 200 and is not having any effect on the object at memory location 100. This explains the third line of our program output printing blue color=Red.
I hope the above explanation clears all the questions. Just remember that variables are references or pointers and its copy is passed to the methods, so Java is always passed by value. It would be more clear when you will learn about heap and stack memory and where different objects and references are stored.