Java implicit widening and narrowing conversions before autoboxing

Posted by Daniel B. Roy on 2 December 2009

Tag(s): Webapplicaties, Artikel

Just for fun, and to add several extra capitals to the end of my name, I decided to take the Sun Certified Java Programmer exam recently. I used this book to prepare which gets a BIG thumbs up. If you already know how to program and want a book that covers all topics, but can also double as a general reference work, this is your best choice. Being used to the extremely low standard of most MSPress exam prep books, this was a refreshingly intelligent and complete book, with some very challenging questions. Having studied the book, the exam was a breeze.

Anyway, one specific subject gave me some confusion. As you probably know, the basic variable types of Java are available in both a primitive and an object version. For instance, you have both an int (primitive) and an Int (class) type. The object variant can be used where you need an object (such as when defining generics), and comes in handy in several other situations.

Now, when you assign an Int object to an int primitive, Java automagically converts one type to the other: this is called autoboxing. This is an implicit conversion, which in a strictly typed language is not to be taken lightly: there have to be strict rules about when implicit conversions are allowed to prevent the compile-time type safety from eroding.

So what happens when you assign a byte primitive to an Int object? This requires TWO implicit conversions: first an implicit 'widening' conversion from byte to int, followed by an implicit 'autoboxing' conversion from int to Int. To understand this, remember that there is no parent-child relationship between the Int and Byte objects, so you can't directly cast a Byte to an Int. The book is somewhat unclear as to when these widening and narrowing conversions before autoboxing are allowed. To make matters worse, the popular Eclipse IDE doesn't follow the rules here. After some experimenting, this is what I deduced:

  • On assignment an implicit widening conversion can be performed before an autoboxing conversion. This is only possible if the value that is being assigned is a compile-time constant and if the target type is no larger than Character. So before autoboxing the following implicit widening conversions are possible: byte->short, byte->char, short->char.
  • The other way round, implicit narrowing of the primitive followed by autoboxing, is also possible for compile-time constants from a source type no larger than int to target types no larger than Character.

Summarizing: when an autobox is involved, implicit widening and narrowing before the autobox is possible, if the value involved is a compile time constant no larger than int and the target type is no larger than Character. 

What's confusing in all this is that the Eclipse compiler also seems to allow implicit widening before autoboxing for a target type Integer. So with Eclipse byte->Integer, short->Integer and char->Integer is compiled, while javac won't allow this. Interestingly, the byte code Eclipse generates will run without problem on Sun java.

Post a comment:

Name:
E-mail*:
Comment:
*optional, will not be published.