Search This Blog

Switch/Case and Autoboxing/Autounboxing

Because I have seen people trying this several times in the last couple weeks I decided I might just as well write a post about it: A seemingly common misconception of Java 5's auto(un)boxing.

While it has been a while now since we moved to Java 5 only now are people slowly getting familiar with the new syntax features. Most of them learned Java beginning with 1.4 and have a history in the DBase or FoxPro world. So object oriented programming and Java as one implementation of it are understood, however maybe not as deeply as you would expect. Some are especially impressed by the ease of use autoboxing and -unboxing bring to the wrapper classes for primitives. I also find that feature quite useful, because objects falling out of the persistence framework have full-blown object types for boolean values or numbers. This makes it rather cumbersome to work with them. Autounboxing helps a lot there:

Undeniably the second example is much easier to read. It becomes even more obvious once you start doing calculations based on wrapped primitives. Nevertheless problems may arise if you do not know what this new syntax will do under the covers. In the above case it is quite clear that the compiler will just put the calls to ".booleanValue()" and ".intValue()" into the bytecode on your behalf.

Thanks to autoboxing the reference type variables "one", "two" and "three" can be assigned using a primitive int on the right hand side of the "=" sign. And because of the autounboxing of "three" in the first line of "main()" it can be assigned to "myInt". After that you find just a regular switch/case construct on that primitive int.

At index 3 in "main()" you can see the automatically inserted call to java.lang.Integer.intValue(). This is the autounboxing. In the static initializer it goes the other way round: The compiler inserts java.lang.Integer.valueOf(int) at indexes 1, 8, and 15. Here the autoboxing takes place.

I have seen this pattern numerous times, and whenever someone comes across it they seem to wonder what the difference is compared to the first example and why they get a compile error. They expect unboxing to happen at each "case". However they do not realize that this is not the same as putting the primitive value there, but is resolved to a method call under the covers - which of course is illegal in that context.

I have found it helpful to show people the bytecode output that gets generated in the first case. As a side effect they also usually learn for the first time about the existence of decompilers :)

One last piece of advice: Eclipse has a feature to specify a different syntax coloring for places where autoboxing and -unboxing occur. I recommend defining a clearly recognizable format, e. g. I use underlined text in a dark red color. I find it rather helpful to remind me that sometimes in such situations a null-check is a good idea - after all reference types might be null opposed to primitive values.

Comments

Popular posts from this blog

Today I had to look at a piece of code a colleague had written, using my XPathAccessor class. She used it in a servlet which gets XML formatted requests. As those are generated by an external 3rd party tool we agreed on some XML schema definitions. Everything they send us needs to conform to its corresponding schema, each reply we send gets validated against a different set.In order to allow independent testing on either side, we provided a little test kit that allows testing our system without having to set up a servlet engine. Basically it just takes a file, reads it into a String and hands that to the handler.First it gets parsed without validation. This is necessary to find out which type of request we were send (the address is the same for all of them). After the root element is known, it will be read again, this time using the right schema to verify the request.Once that is done, some reply is put together and sent back to the client. So far, so good.When I looked at the code I …

(Also see the follow-up post about some progress)Today I was (again) facing a log file from a machine that had for some reason not been able to start a temporary MySQL daemon during the night to prepare for a streaming MySQL slave installation. The necessary 2nd daemon had created its new ibdata files, however just after that aborted the startup process with the following message:Can't start server: Bind on TCP/IP port: No such file or directory
071001 23:09:55 [ERROR] Do you already have another mysqld server running on port: 3310 ?
071001 23:09:55 [ERROR] Aborting
071001 23:09:55 [Note] mysql\bin\mysqld.exe: Shutdown completeAs you can see, the port is a different one from the default MySQL port, so I can be sure there was no conflict with the primary instance. Even more curiously the same process has been working on that and other machines flawlessly for some time. However I remember having seen this message once before, but back then I did not have the time to look into it any…

Some words in advance...Recently I wrote about multi-threading problems with java.util.Calendar and java.text.DateFormat. The last sentence was So maybe it is time to search your code for all static usages of the Calendar and various ...Format classes, before you start getting strange errors.Searching code is not very practical, especially if you do it manually. Everyone knows you can look at code for hours, without seeing an problem - and as soon as it has reached production systems it starts breaking up in various ways :-)Fortunately smart and reknown people have devised ways of making the computer look for bugs automatically. Amongst others, FindBugs is a very nice - and free - tool that analyzes your Java application's compiled bytecode and looks for numerous so called bug patterns. Those patterns are divided into categories, such as "Bad practice", "Correctness", "Multithreaded correctness", "Performance" and some more. Each of them lo…