Reputation: 1485
I know that everything in java is passed by value but shouldn't the below code print 2 instead of 1.
All I am doing is passing Integer
and changing its value. Why is it printing 1 instead of 2 ?
public static Integer x;
public static void doChange(Integer x) {
x = 2;
}
public static void main(String arg[]) {
x = 1;
doChange(x);
System.out.println(x);
}
Upvotes: 3
Views: 16219
Reputation: 538
You changed your parameter, not your class variable. Rename your parameter and it will work:
public static void doChange(Integer unused)
{
x = 2;
}
The reason is that with the assignment (=) you changed the instance. Your parameter x is than assigned to a new instance (not the one you give it with the method call). The solution will be to call instance method to change the state of the instance. But: the object class of scalar don't work like other classes. The instance of Integer are unique (immutable), you cannot change the state of an Integer instance.
But, if you try it with class of your own like MyNumber and use instance method calls (not assignment =), it will work as you expected:
public class MyNumber {
private int number = 0;
public set(int v) {
number = v;
}
public get() {
return number;
}
public String toString() {
return Integer.toString(number);
}
}
If you use MyNumber instead of Integer change your method doChange to:
public static void doChange(MyNumber x)
{
x.set(2);
}
And of course change the declaration to:
public static MyNumber x;
... and the first assignment in main to:
x.set(1);
Hope it helps to understand.
Upvotes: 0
Reputation: 1485
thank you so much for your answers. i think i know now what is happening under the hood. i think the reason i am not able to see changes in main function is because integer is immutable and when i am assigning new value to it, its creating new object and assigning to the reference x;
if we can repeat same example with mutable data we ll see different output.
public static StringBuilder x;
public static void doChange(StringBuilder x)
{
x.append("world");
}
public static void main(String arg[]) {
x = new StringBuilder("hello ");
doChange(x);
System.out.println(x);
}
output: hello world
Upvotes: 5
Reputation: 592
You are passing an object, Integer to doChange function. Inside doChange() you are assigning a new value, and Java is autoboxing, that is creating a new Integer object with value 2 and making your parameter point to it.
A variable that points to an object is basically a pointer to a memory address: See these answers: https://stackoverflow.com/a/1750197/2698109 and https://stackoverflow.com/a/1750141/2698109
public static Integer x; // an primitive Object
// passing an object
public static void doChange(Integer x) {
// under the hood Java is doing this
x = new Integer(2);
}
Change your method signature to
public static void doChange(int x) {
And it should work as expected.
Upvotes: -1
Reputation: 429
This is how you would resolve your issue in code. I made up a class named La
. Notice the La.x = 2;
statement inside the doChange()
method.
public class La {
public static Integer x;
public static void doChange(Integer x) {
La.x = 2;
}
public static void main(String arg[]) {
x = 1;
doChange(x);
System.out.println(x);
}
}
Upvotes: 0
Reputation: 159106
A boxed int
is still immutable, and x
in doChange
refers to the parameter, not the field. To show what's going on, here is the explicitly boxed version of your code.
public static Integer x;
// parameter 'x' is hiding field 'x'
public static void doChange(Integer x)
{
// Update parameter 'x', not field 'x', to point to
// new Integer object with value 2.
// Since 'x' is by-value, caller will not see change
x = Integer.valueOf(2);
}
public static void main(String arg[]) {
x = Integer.valueOf(1);
doChange(x);
System.out.println(x);
}
Upvotes: 2
Reputation: 3785
You answered your own question :) .
Since its passing by value, doChange() method will have a copy of value . So whatever it does inside that method it will not effect actual "x" variable which is declared inside main method.
Upvotes: 0