Thursday, December 20, 2007

Java 1.5 Explained - Autoboxing

Here's the start of a short series on how many of the new language features were added in in Java 1.5. I'm going to start with Autoboxing. Autoboxing is language feature that allows you to write code using primitive types where previously you had to use the object equivalent. For example, the primitive type int not the same as Integer. You can convert between the two manually but that can be cumbersome. There's also extra code required when you're dealing with lists, sets, maps, etc., since you cannot store primitive types in collections.

Let's look at some code:
List list = new ArrayList();
list.add(100); // instead of list.add(new Integer(100));
Adding a primitive int to a list is now super easy.

So how is this actually working? Primitive types are not magically objects in Java 1.5. The 1.5 compiler is doing tricks behind the scenes to make writing code easier. Let's take a look:
List list = new ArrayList();
list.add(100);
list.add(200);
int i = list.get(0);
Integer j = list.get(0);
This code adds two primitive ints to a list and then gets them in two different ways. The compiler generates the following byte code:
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."":()V
7: astore_1
8: aload_1
9: bipush 100
11: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
14: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
19: pop
20: aload_1
21: sipush 200
24: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
27: invokeinterface #5, 2; //InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
32: pop
33: aload_1
34: iconst_0
35: invokeinterface #8, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
40: checkcast #9; //class java/lang/Integer
43: invokevirtual #10; //Method java/lang/Integer.intValue:()I
46: istore_2
47: aload_1
48: iconst_0
49: invokeinterface #8, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
54: checkcast #9; //class java/lang/Integer
57: astore_3
Interesting things start on line 11. The compiler added some extra code to call Integer.valueOf(100) so the 100 value can be added to the list. It's the same code you'd normally have to write yourself, but now autoboxing is doing it for you.

Next look at line 35. The generated code is calling the list get method and returning an object. The object is then cast to an Integer and the intValue method is called to obtain the primitive type. Again, it's the same code you'd have to write but you don't have to anymore.

You can compare the byte code for the list.get(0) that returns and Integer. It's the same byte code generated for autoboxing.

You'll see there's some use of generics here since the list.get(0) doesn't have to do any casting to an Integer. I'll cover generics in detail later. That's about it for autoboxing. Go back to enjoying using primitive types and not having to manually create all those Integer and Long objects.

1 comment:

Javin @ FIX Protocol Tutorial said...

Hi,
Autoboxing is a great feature provided by JAVA5 but using it blindly may result in very subtle problem which will take hours and hours to
debug and find. to read more see the link
What is the problem while using '==' in autoboxing world in Java 5 ?

Thanks
Javin