arshid dar
arshid dar

Reputation: 1485

function won't change value of variable in java?

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

Answers (6)

dev.null
dev.null

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

arshid dar
arshid dar

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

eribeiro
eribeiro

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

javaauthority
javaauthority

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

Andreas
Andreas

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

Rahman
Rahman

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

Related Questions