Autoboxing could catch you out

A colleague pointed out an aspect of auto boxing in Java 5 that could catch you out. Which I have hopefully captured in the following contrived little unit test.

@Test 
public void shouldTakeCareWithAutoBoxing() throws Exception { 
  Map<String, Integer myMap = new HashMap<String, Integer>(); 
  String letters = "Gotchas"; 
  Integer count = 0; 
  
  myMap.put(letters, count); 
  // count the letters 
  for (int i = 0; i < letters.length(); i++) { 
    count++; 
  } 
  
  assertSame(letters.length(), count); 
  assertNotSame(letters.length(), myMap.get(letters)); 
  assertNotSame(count, myMap.get(letters)); 
}

Auto boxing allows you to do seemingly convenient things, such as manipulate your Integer object like you would a primitive. However, Integers are immutable and what incrementing count is doing behind the scenes is referencing a new instance of an Integer with the updated value. Therefore count no longer references the object placed in the Map, that’s the old object…

Putting the each incremented value in the map would at least give you what you might be trying to achieve…

// count the letters 
for (int i = 0; i < letters.length(); i++) { 
  myMap.put(letters, ++count); 
  } 
  
  assertSame(letters.length(), count); 
  assertSame(letters.length(), myMap.get(letters)); 
  assertSame(count, myMap.get(letters));

…but it’s not nice.

Following a quick google search I found Autoboxing Considered Harmful which provided an even more interesting aspect, which I have reproduced here as a simple JUnit test.

import org.junit.Test; 
import static org.junit.Assert.*; 

public class FurtherExperimentsInAutoBoxing { 
  
  @Test 
  public void twoObjectsWithTheSameValueShouldNotBeTheSame() throws Exception { 
    Integer a1 = new Integer(150); 
    Integer a2 = new Integer(150); 
    
    assertNotSame(a1, a2); 
  } 
  
  @Test 
  public void withAutoboxingTheyCanAppearToBe() throws Exception { 
    Integer a1 = 100; 
    Integer a2 = 100; 
    
    assertSame(a1, a2); 
  } 
  
  @Test 
  public void sometimesAnyway() throws Exception { 
    Integer a1 = 150; 
    Integer a2 = 150; 
    
    assertNotSame(a1, a2); 
  } 
}

As the original author points out in their post, this is not the way you would want to write these, but for someone trying to grasp the concepts of what an object is and how to deal with them, these language features wouldn’t exactly help.

comments powered by Disqus