How can I change Integer value when it is an argument like change array's value?

27,292

Solution 1

You can't change the value of the variable i in main from within the p1 method, because the argument is passed by value: the parameter i in p1 is entirely separate from the i variable, it's just that they have the same value at the start of the method. Java always uses pass-by-value semantics - but when the parameter type is a class, it's a reference that is passed by value.

In fact, you're not changing the value of arr, either - it's a reference to the same array as before, but the value in the array has been changed. And that's what you can't do with Integer, because Integer is an immutable type.

If you want a mutable class like Integer, you could use AtomicInteger instead:

public static void main(String[] args) {
    AtomicInteger i = new AtomicInteger(0);
    modify(i);
    System.out.println(i);
}

private static void modify(AtomicInteger x) {
    x.set(2);
}

I would usually not do this, however - I usually try not to modify the objects that method parameters refer to. Instead, I write methods which compute a single result, and return that.

Solution 2

You can use AtomicInteger, which allows changing, instead of Integer:

public static void main(String[] args) {
    AtomicInteger i = new AtomicInteger(0);
    p1(i);
    System.out.println(i);
}


public static void p1(AtomicInteger i) {
    i.set(2);
}

Solution 3

Simply put: You can't, because Integer is immutable and you only get the object address by value, so swapping the whole object is not possible because after the method finished, the old object gets reassigned.

Share:
27,292
cow12331
Author by

cow12331

Updated on October 04, 2020

Comments

  • cow12331
    cow12331 over 3 years
    public static void main(String[] args) {
        Integer i = new Integer(0);
        int[] arr = {1};
        p1(i);
        p2(arr);
        System.out.println(i);
        System.out.println(arr[0]);
    }
    
    
    public static void p1(Integer i) {
        i = 2;
    }
    
    public static void p2(int[] i) {
        i[0] = 2;
    }
    

    //output: 0, 2

    How can I change the value of i like I change the value of arr?

  • Dmitry Ginzburg
    Dmitry Ginzburg over 9 years
    It's absolutely inappropriate to use reflection in this case.
  • walkeros
    walkeros over 9 years
    @Dimitry: Why do you think so? It is not beautifull. That's true, but this is what reflection was ment for.
  • Dmitry Ginzburg
    Dmitry Ginzburg over 9 years
    Reflection should be used, when nothing else can be used. There, Integer may be replaced with AtomicInteger or OP can pass array (not so good as using just some king of mutable Integer, but also possible).
  • walkeros
    walkeros over 9 years
    I totally disagree. AtomicInteger is not an Integer at all. It extends number only to allow it to be used in numeric operations. You can not suggest anyone to use AtomicInteger in place of Integer (consider performance of AtomicInteger for example).
  • walkeros
    walkeros over 9 years
    That's not an answer to a problem, since AtomicInteger is not an Integer at all. And you answered wrongly. The argument is NOT passed by value. It is passed by reference since this is and Integer object (not the primitive int).
  • Jon Skeet
    Jon Skeet over 9 years
    @walkeros: No, it's really not passed by reference, because nothing is passed by reference in Java. Please read javadude.com/articles/passbyvalue.htm or some of the hundreds of questions on this topic on SO. I've explained that what the OP asked can't be done directly, so I've given an answer with a similar (but mutable) type.
  • Jon Skeet
    Jon Skeet over 9 years
    This is absolutely not what reflection is meant for. If I ever saw this in a code review, I would reject it immediately. Does it work? Yes. Should it be used? Never.
  • cow12331
    cow12331 over 9 years
    Any boolean type like atomicinteger?
  • Jon Skeet
    Jon Skeet over 9 years
    @cow12331: AtomicBoolean?
  • walkeros
    walkeros over 9 years
    @Jon Who said that you would get this for code review?;) This is not for solving usual cases. This is for solving the problem in some rare cases.
  • Jon Skeet
    Jon Skeet over 9 years
    There are plenty of times that reflection is useful in perfectly reasonable ways. This is not one of those times. Heck, it becomes even worse if you're passed in the result of autoboxing a small int, as then the mutated (polluted!) object will be used every other time you autobox the same value. Code like this should come with a much stronger health warning than "only by using some hacks"...
  • Dmitry Ginzburg
    Dmitry Ginzburg over 9 years
    @JonSkeet Thanks, Jon, you're writing exactly what I couldn't word.
  • walkeros
    walkeros over 9 years
    Yes you are right, but using reflection to change a value in any way is a hack. When you use reflection you are putting your code at risk. After all when you access and read value of any private field for example you are risking that this field may no longer be present there when you checkout new version of library/code. Therefore you are not writing anything new :) It's always your decision to use reflection or not. If you use it you need to be aware of consequences.
  • Jon Skeet
    Jon Skeet over 9 years
    There are plenty of times when reflection is used without accessing private fields at all. And yes, I agree that you need to be aware of the consequence - so why didn't you warn the OP (who is presumably fairly new to Java) of the risks that this "solution" involves?
  • walkeros
    walkeros over 9 years
    @Jon the reference to the object is passed by value which effectively acts as if object was passed by reference. I do not want to open discussion here, but pointing out in this case that objects are passed by value can trully mislead the person reading
  • Jon Skeet
    Jon Skeet over 9 years
    @walkeros: No, it doesn't act as if it were passed by reference - because otherwise changing i in the method would modify the caller's variable. (That's what pass-by-reference is all about.) Note that I didn't say that an object is passed by value - I said that the reference is passed by value. You're the one being misleading - and inaccurate - here, I'm afraid, by claiming Java uses pass-by-reference. Compare this with a language like C#, which by default acts like Java, but also allows pass-by-reference with the ref modifier.
  • walkeros
    walkeros over 9 years
    "hack" is always a warn. IMHO: people in stackoverflow in many cases creates great answer, but also tend to write more than the person asking the question really would like to hear.
  • walkeros
    walkeros over 9 years
    @JonSkeet ok you wrote this sentence in right way. I should have written that reference is passed in comparison to that "it is passed by reference". You have my vote up in exchange;)
  • Jon Skeet
    Jon Skeet over 9 years
    @walkeros: I would rather write more than an OP wants to hear, but tell them everything they need to hear than practically invite someone to do something very dangerous, without outlining the risk.
  • walkeros
    walkeros over 9 years
    @JonSkeet: Let it be then :)
  • walkeros
    walkeros over 9 years
    Interesting thing... giving -1 vote for correct solution. For people who do this instead of understanding why it can be done I would suggest reading all the comments here. If you still want to give -1 I would think if you ever needed to solve more complicated problems in java than just creating service in spring.
  • DàChún
    DàChún about 7 years
    Did you verified it? actually it doesn't work at all
  • walkeros
    walkeros about 7 years
    @User9527 I have just run it.. works. This code final Integer integer = new Integer(3); System.out.println(integer); p1(integer); System.out.println(integer); prints 3 and 2.
  • DàChún
    DàChún about 7 years
    sorry, my bad. I was using i = 0; in that case i is int instead of Integer. You are right.
  • Chinmay
    Chinmay over 6 years
    thanks for mentioning "Integer is an immutable" for which it didn't get updated.
  • Christophe Roussy
    Christophe Roussy about 6 years
    @walkeros Dude: you are talking to Jon Skeet
  • Kartik Chugh
    Kartik Chugh over 5 years
    This was the best answer for me