Jul 152004
 

Just wanted to discuss quickly a few simple best practices for auto-boxing in Java. This will help prevent shooting ones self in the foot. These suggestions go back to my rule of thumb for auto-boxing:

If you can use primitives do it, if you can’t don’t.

So here are a few simple auto-boxing rules. These apply mostly to usages of primitives verses wrapper classes, because at the end of the day, that’s what auto-boxing is all about.

1. Avoid using wrapper classes whenever possible.

Wrapper classes should only be used whenever you absolutely cannot use a primitive. Otherwise, either auto-unbox (de-autobox) the value and use the primitives.

2. Never do math with wrappers.

This is a simple one that instinctively goes along with #1. Doing math with wrapper classes forces a auto-unboxing operation to occur for each operator. Therefore, this code will cause five auto-unboxing operations and two auto-boxing operation to occur:

This code generates this byte code:

As you can see, the valueOf method is used to auto-box the initial value and the intValue method is used to auto-unbox the values. The auto-unboxing happens five times and the auto-boxing happens twice. If we use primitives instead, this is the bytecode that is created:

Much simpler and no object creation or method calls. This code will perform much faster than the previous example and therefore using primitives is always preferred when doing any math at all.

This applies to for loop variables and counts. Using an Integer as a loop variable can reduce performance of that loop because of the need to create new objects each loop iteration during the auto-box operation.

3. Try not to use any of the comparison operators (<, >, <=, >=, ==, etc) with wrappers.

Auto-boxing allows you to use all of the comparison operators, except the ==. It will de-autobox (auto-unbox) the values and compare them correctly. The problem here is that each comparison will cause an auto-unboxing to occur and it also promotes bad style with respect to wrapper usage. In addition, since we don’t get the == operator, to be consistent the rest of those operators should be avoided. This is more of a coding style and practices thing, but if you are going to be doing comparisons, you should probably unbox the values.

4. Avoid usage in loop statements.

Using wrapper classes in statements is not as much of a performance drain as doing math with them, but it does introduce a method call during each loop iteration in order to auto-unbox the values in order to do the comparison. This is an extension to rule #3 for capturing usages in do, while, and for loops. This usage is not preferred:

This will auto-unbox the len variable during each loop iteration. Although this is simply a method call to the intValue method, it should still be avoided. This is better:

5. Always check for null values.

This is a bit teadious, but when wrapper class variables are null a NullPointerException will be thrown when doing auto-unboxing. This code illustrates this problem:

You can use terenary expresions to prevent the NullPointerExceptions or write a toolkit to do this. Toolkits in conjunction with static imports reduce the code mess of terenary expressions. Here is an example of both:

Any which way you slice it, you want some easy method for handling null values when you know that they are possible. If they aren’t possible, then this rule can be ignored.

Jul 142004
 

There has been a lot of talk lately about the JDK 5 auto-boxing issues and how everyone thinks it should work or whether or not it should even exist. The main thread I found and posted to was over here.

Just wanted to discuss this in some more detail. Auto-boxing is 100% code-generation. It is an auto-conversion between objects and primitives. Here’s what that means. If you code this:

Java generates code that actually does this:

Okay, what does this mean? It means that the int passed into the valueOf method is converted to an Integer AND if it has already been converted, Java can choose to return the previously created Integer or a new Integer. This allows Java to cache the instances of Integer so that the memory footprint is smaller. This means that two separate calls to this method with the same int MIGHT return the same object. Here’s an example:

So, what does it print out? Totally unknown! Why? Because any JVM can implement this method anyway it sees fit. The fact that Sun’s JVM caches values from -127 to 127 is completely arbitrary. The contract of this method states:


Returns a Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values.

It doesn’t tell us when it caches or how it caches, just that it can cache. So, why not just not cache and make everyone’s lives easy? Because doing that would mean that every autobox operation would create a new object. This might seem relatively low concern for people who are simply putting things into Maps, but for those people that are fetching values from Maps and doing math with those values and putting the result back into the Maps, this would slow the application down.

Okay, now that the way things works has been covered, here’s what I think about autoboxing use. As I said on the thread over at TheServerSide: if you can use primitives do, if you can’t don’t. Simple huh? Well, it makes good sense because for performance reasons, you still do not want to incur the overhead of calling valueOf if all you are doing is counting. That just wouldn’t make any sense. Likewise, if you are putting values into a Map and the key is an index or primary key from a database, doesn’t make sense to use an int.

What I think about the use of valueOf? Well, I think it’s fine. I know better than to ever compare Objects using the == operator and everyone else that uses Java should know this as well. For that matter, you should know whether or not you have autoboxed something and which equality operation is correct (== or .equals()). I think that my rule from above helps to clarify this issue. If you are using primitives, you are probably doing math of some sort. This usually entails equality operations or something similar (greater-than, less-than). In these situations, you can safely use ==. However, if you can’t use primitives, than you shouldn’t right? In these cases you are mostly passing int into methods that take either Object, Number of Integer. Therefore, you shouldn’t be doing an comparisons on these values.

I can already see the responses… What if I am summing values in a Map and want to break when the sum is a certain value? Okay, if you can use primitives do so:

If you can’t, don’t.

To me this makes sense. Java’s de-autobox gets us back to a state where we can use primitives. All the operations we do on that primitive can be done on primitives, so we go ahead and do it. Then we get back to the case where we can’t use a primitive because the method requires an Integer. Therefore, we allow the Java compiler to autobox the value for us.