Wrapper Classes
Remember that primitive types are not objectsthey do not inherit from the class java.lang.Object. The java.util.List interface only supplies an add method that takes a reference type as a argument. It does not supply overloaded add methods for each of the primitive types. In order to store the int charge in a collection, then, you must convert it to an object. You accomplish this by storing the int in a wrapper object. For each primitive type, java.lang defines a corresponding wrapper class.[8]
Each wrapper class provides a constructor that takes a primitive of the appropriate type as argument. The wrapper stores this primitive and allows for extracting it using a corresponding getter method. In the case of the Integer wrapper, you extract the original int by sending the message intValue to the wrapper. A test (in StudentTest) for the example:
If you had to write the implementation using pre-J2SE 5.0 code, it would look something like this:
The addCharge method shows how you would wrap the int in an instance of the Integer wrapper class in order to pass it to the add method of the charges collection. When iterating through the collection (in totalCharges), you would have to cast each retrieved Object to the Integer wrapper class. Only then would you be able to extract the original int value through use of the intValue method. J2SE 5.0 simplifies the code through the use of parameterized types and the for-each loop.
In addition to allowing you to wrap a primitive, the wrapper classes provide many class methods that operate on primitives. Without the wrapper classes, these methods would have nowhere to go. You have already used the Character class method isWhitespace. A further simplification of the code comes about from one of the new J2SE 5.0 features, autoboxing. Autoboxing and AutounboxingAutoboxing is the compiler's ability to automatically wrap, or "box" a primitive type in its corresponding wrapper class. Autoboxing only occurs when Java can find no method with a matching signature. A signature match occurs when the name and arguments of a message send match a method defined on the class of the object to which the message is being sent. An argument is considered to match if the types match exactly or if the type of the argument is a subtype of the argument type as declared in the method. As an example, if Box declares a method as:
then any of the following message sends will resolve to this add method:
The second add message send works because ArrayList is a subclass of List. If Java finds no direct signature match, it attempts to find a signature match based on wrapping. Any method with an Object argument in the appropriate place is a match. In the addCharge method, the explicit wrapping of the int into an Integer is no longer necessary:
It is important for you to understand that the wrapping does occur behind the scenes. Java creates a new Integer instance for each primitive value you wrap. Autoboxing only occurs on arguments. It would be nice if autoboxing occurred anywhere you attempted to send a message to a primitive. This is not yet a capability, but it would allow expressions like:
Autounboxing occurs when you attempt to use a wrapped primitive anywhere a primitive is expected. This is demonstrated in the following two tests:
The more useful application of autounboxing is when you extract elements from a collection bound to a primitive wrapper type. With both autoboxing and autounboxing, the charge code in Student becomes:
You will learn about addition capabilities of wrapper classes in Lesson 10 on mathematics. |
Friday, October 30, 2009
Wrapper Classes
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment