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
Are arrays pass by reference or pass by value?
In java except the primitive data types like int, char everything else is pass by reference is a wrong concept. Everything is pass by value. In case of objects you are passing the reference of the object to the new object . The references are passed by value. For ex arr[ ] = new int[5]; Here arr is a variable pointing to a memory location of array of int. Now consider,
Fn(int[ ] arr2){ .... }
Call fn(arr);
Here the reference of arr that is the memory location of where the array of integer starts will be given to arr2.
Hope this clears your confusion.
More on reddit.comVideos
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)