Does Java return by reference or by value

28,682

Solution 1

The get method returns a copy of the reference to the stored integer...

Assigning a new value to the variable storing this copy in order to point to the value 10 will not change the reference in the map.

It would work if you could do balance.setValue(10), but since Integer is an immutable class, this is not an option.

If you want the changes to take affect in the map, you'll have to wrap the balance in a (mutable) class:

class Balance {
    int balance;
    ...
}

Balance balance = cardNumberBalance_.get(cardNumber);
System.out.println(balance.getBalance());
balance.setBalance(10);
Balance newBalance = cardNumberBalance_.get(cardNumber);
System.out.println(newBalance.getBalance());

But you would probably want to do something like this instead:

cardNumberBalance_.put(cardNumber, 10);

Solution 2

The Integer variable contains a reference to an Object. The Integer object is immutable and you cannot change it. When you perform

balance = 10; // replace the previous Integer reference with a different one.

The normal way to do this is to use

cardNumberBalance_.put(cardNumber, 10);

An alternative which is not used so often is to use AtomicInteger or use your own MutableInteger

private final Map<String, AtomicInteger> cardNumberAndCode_ = new HashMap<String, AtomicInteger>();

AtomicInteger balance = cardNumberBalance_.get(cardNumber);
balance.set(10);

Solution 3

Java does not support pass-by-reference (and return-by-reference). See Is Java "pass-by-reference" or "pass-by-value"?

Solution 4

The result of assignment

balance = 10;

is that a new instance of Integer is created with value of 10, and its reference is assigned to balance variable. It does not change the object that you get from the map, that is the object stored in the map is unchanged.

If you need to change the value of balance, you have to wrap it in a mutable class just like aioobe describes.

Share:
28,682
Merni
Author by

Merni

Updated on September 17, 2020

Comments

  • Merni
    Merni over 3 years

    I have a HashMap:

    private HashMap<String, Integer> cardNumberAndCode_ = new HashMap<String, Integer>();
    

    And later I do this:

    Integer balance = cardNumberBalance_.get(cardNumber);
    System.out.println(balance);
    balance = 10;
    Integer newBalance = cardNumberBalance_.get(cardNumber);
    System.out.println(newBalance);
    

    First it prints 1000, and the second time it's printing 1000, the value does not change. Why is Java returning the Integer by value and not by reference?

  • aioobe
    aioobe over 12 years
    You can't do it like that... You'll have to wrap the balance in a separate mutable class... Note also that Integer is an immutable class.
  • Jon Skeet
    Jon Skeet over 12 years
    Objects themselves are never passed. References are passed (or returned) by value. This is a subtle but important distinction to make.
  • Vishy
    Vishy over 12 years
    @Jon Skeet, The wording wasn't correct. I have tried to fix it.
  • Jon Skeet
    Jon Skeet over 12 years
    Much better, thanks. Sorry if it seemed harsh to downvote, but I've been fighting against uses of the term "pass by reference" with respect to Java for years :)
  • Vishy
    Vishy over 12 years
    @Jon Skeet, I fully understand. ;)
  • Stephen C
    Stephen C over 12 years
    @aioobe - Would you say that a method returns "a copy of true" or a "copy of 42"? Well a method that returns a reference doesn't return "a copy" either. It just returns THE reference.
  • aioobe
    aioobe over 12 years
    Ah, ok. Depends on whether you use the word "reference" to mean the value it contains, or the variable though. But I see your point.