Gradually excavate autoboxing / auto-unboxing simpler integrated two sets of system
Sun Haitao (Sun.haitao@126.com)
July 29, 2004, was originally published, and finally revised on August 11, 2004
J2SE 1.5 provides the mechanism for "Autoboxing" and "Auto-UnboXing", allowing the compiler to perform transformation work between basic types and their parcel objects, enabling it to avoid simultaneous ways to avoid simultaneous There are some troubles from two types of systems. This paper introduces the use of the use of the Autoboxing / Auto-Unboxing mechanism, the effect, the occurrence timing, limit, the impact of the overload mechanism, and the impebrarence of performance.
Traditionally, in the Java program, you can put an object directly into a container (whether it is still map); however, if you intend to put in a number, character or Boolean, you must join a "generation" The steps of wraping their objects.
The reason for this phenomenon is that there is always two very different types of systems in the Java language:
A set is called "Reference Types", including all classes and interfaces. These types of data are viewed as objects, so you can save it with an Object type variable. A set of "Primitive Types, including: Byte, Short, Int, Long, Float, Double, CHAR and BOOLEAN. These types of data are not objects, so they cannot be saved with an Object type variable.
At the same time, the two sets of types can be used to obtain some performance benefits - because the basic type of data is not an object, so it is created, the space occupied is less, and the resource that is recovered is more easier; however, this The approach also causes some coding problems - for example, a variable (or array) cannot be defined, allowing it to save basic type data, and save the reference type data (similar, can not define one simultaneous Match the interface of these two types of data, but this problem can be avoided by means of the overload mechanism in Java).
In fact, when you need to define the variables (and formal ginseng) that "I don't know what type of data used to save, this problem is generally taken to take evasive attitude, define their types to Object, and then can be referred to as" boxing "and "Unboxing" operation to solve the problem that Object does not cover basic types.
Boxing and unboxing operations
The so-called boxing operation refers to a place where the basic type of data can only be accepted by generating an object that can wrap the basic type data.
Listing 1: Typical situation for manual boxing
COLLECTION INTEGERS = New ArrayList ();
For (int i = 0; i <10; i ) {
Integers.Add (
NEW INTEGER (i));
}
The class used to generate these objects is referred to as "wrapper classes). The wrapping classes in Java have eight kinds of Byte, Short, Integer, Long, Float, Double, Character, and Boolean (all in java.lang package), which are used for parcel Byte, Short, Int, Long, Float, Double , CHAR and BOOLEAN types of data.
The so-called unboxing operation refers to the corresponding method of adjusting the wrapping class object to obtain the "basic type of data" they represent for further disposal.
Listing 2: Typical situation for manual unboxing for (Iterator ITR = Integers.ITerator (); itr.hasnext ();) {
Integer i = (Integer) ITR.NEXT ();
System.out.println (
I.intValue () 1);
}
In the latest version of Java language - J2SE 1.5, "Autoboxing" and "Auto-UnboXing" mechanisms can be made to make these trivial operations to complete these trivial operations to integrate with a simpler way. Two sets of type systems.
Familiar strange noun
Although this pair of operations have a long history, they are called "boxing" and "unboxing" practices. It is basically a wide accepted acceptance after the concept of "AutoBoxing" and "Auto-Unboxing". Before that, they did not seem to be universal, specialized names. However, since the two concepts were rare, this problem did not have a serious impact.
2. Using autoboxing and auto-unboxing
Using autoboxing and auto-unboxing, do not need any special steps, everything will automatically occur under the compiler.
It can now be treated with an INT type data:
Listing 3: Automated Boxing operation
Collection al = new arraylist ();
Al.Add (
1);
Because the compiler will quietly convert this code into this:
Listing 4: Equivalent form after Autoboxing
Collection al = new arraylist ();
Al.Add (
Integer.Valueof (1));
The value of the INT type used here is parameter, generating the valueof method of the Integer instance, which is the newly added content in J2SE 1.5. Other wrapping classes also have values that can accept the corresponding basic types of values, and generate the valueof method of the corresponding parcel class instance.
This is also possible to treat an Integer type object:
Listing 5: Automated unboxing operation
Integer One = new integer (1);
Int two =
One 1;
Because the compiler will quietly convert this code into similar this shape:
Listing 6: Equivalent form after auto-unboxing
Integer One = new integer (1);
Int two =
One.intValue () 1;
In general, as long as a result type is a basic type of expression, it is possible to induce autoboxing; similar, as long as a result type is the expression of the package, put it The auto-unboxing is induced in the position where the corresponding basic type is allowed.
Source of "autoboxing / auto-unboxing" feature
Many language features added in J2SE 1.5 can find corresponding things in C #. However, according to Bruce Eckel's interview with Joshua Bloch, although Java's R & D team did pay attention to C # (Joshua Bloch himself put a book about C # books), but only "Autoboxing / Auto-Unboxing" and "Metadata" indeed It is the characteristic of directly drawing from C #.
3. ActOboxing specific timing
There are three specific opportunities for Autoboxing, mainly there are such three:
Assign the basic type of data to the variable of the reference type. For example, an INT type data is assigned to an Integer type variable. Listing 7: Data of variables that give reference types Basic Types of data INTEGER i =
31415;
Transmit the basic type of data to the parameter of the reference type. For example, a Boolean type data is transmitted to a parameter defined as Object. Listing 8: Parameters of the reference type for basic types of data
Hashmap map = new hashmap ();
Map.put
True, NULL);
When the basic type of data is converted to the reference type. For example, in front of a long-type data, add (long). Listing 9: Forced transformation from basic types of data to reference types
System.out.println (
(Long) 27828L);
4. AUTOBOXING limitations
Autoboxing mechanism has a limitations - only converts basic types of data to their own wrapping classes (and superior classes of parcels).
Similar to this code cannot work, although INT type data can be represented by a LONG object:
Listing 10: Automatic upward transformation and autoBoxing
INT I = 27828;
System.out.println (
(Long) i); / * Error error * /
This is because this code is actually equivalent to:
Listing 11: AutoBoxing operations occur before the automatic upward transition
INT I = 27828;
System.out.println (
(Long) INTEGER.VALUEOF (i)); / * Compile time error * /
And Integer is not a subclass of long, so this conversion cannot be performed. If you must do this, you need to manually add a transformation:
Listing 12: Need to force up to transition first, then make Boxing
INT I = 27828;
System.out.println ((long)
(long) i);
5. A transo-unboxing specific timing
There are such seven species of AUTO-UNBOXING.
Give the wrap object to the basic type of variable. For example, an Integer type data is assigned to an INT type variable. Listing 13: Passable variable wrapped object assigned to basic types
INT i =
NEW INTEGER (32);
Pass the parcel object to the basic type of parameters. For example, a Boolean type data is transmitted to a parameter defined as boolean. Listing 14: Parametric parcel class object to the basic type
JFrame frame = new jframe ("^ _ ^");
Frame.setsize (320, 200);
Frame.setvisible
New Boolean (TRUE);
When the parcel object is enforced to the basic type. For example, in front of a long-type data, add (long). Listing 15: Forced transformation from the wrapping object to the basic type
Long L = New long (31415L);
System.out.println (
(long) L);
When the wrap object is used as an operator operator. For example, there is a " " between the two BYTE type data. Listing 16: Take the number of operators as operators
BYTE A = New Byte ((byte) 1);
Byte B = New Byte ((byte) -1);
System.out.println (
((A ) << 2) (~ b)); / * Output "4" * /
System.out.println (a); / * Output "2" * /
Use the wrapped object to specify the size of the array. Of course, from semantics, this object must be Byte, Short, Integer, or Character. Listing 17: Use the wrap class object to specify the size of the array character size = new character size = new character ('★'); / * Unicode: 9733 * /
Int [] integers = new int [
Size]; / * Generate an array of available 9733 int elements * /
When using the parcel object in the Switch statement. Of course, from semantics, this object must be Byte, Short, Integer, or Character. Listing 18: Use the package class object in the switch statement
Character C = New Character ('a');
Switch (c) {
Case 'a':
Case 'E':
Case 'I':
Case 'o':
Case 'u':
System.out.println ("a Vowel In English");
Break;
DEFAULT:
System.out.println ("Not a Vowel In English);
Break;
}
When using the Boolean object in the if / for / while / do-while statement, it is used as a conditional expression. Listing 19: Use the Boolean object as a conditional expression
Boolean Bool = New Boolean (Math.random ()> 0.5);
IF (bool) {
System.out.println ("Aye!");
} else {
System.out.println ("NAY!");
}
6. AUTO-UNBOXING limitations
The mechanism for auto-unboxing has such a limitations - can only transform the wrap-up objects to their corresponding basic types (and a wide range of housing range).
Similar to this code cannot work, although 32 does not exceed the range that Byte can represent:
Listing 20: Auto-unboxing and force down transformation
Integer i = new integer (32);
System.out.println (
(Byte) i); / * Compile time error * /
This is because the compiler does not recognize the operation of simultaneous auto-unboxing and forced downward transitions, so this conversion cannot be performed. If you must perform this operation, you need to handle a transformation:
Listing 21: Need to be unboxing, then force down to transform
Integer i = new integer (32);
System.out.println (Byte)
(int) i);
However, it is no problem with the operation of Auto-Unboxing and Forced to-Up-transformation, so the following code works very normal:
Listing 22: AUTO-UNBOXING and mandatory transformation can be performed at the same time
Integer i = new integer (32);
System.out.println (
(double) i);
7. Other situations that cannot be automatically converted
In addition to the limitations of mandatory types of transformation, there is still no autoboxing / auto-unboxing:
1. The basic type of array and parcel array will not be automatically converted. Such a code is not completely accepted by the compiler:
Listing 23: Elements can, container is not
int [] INTS = {1, 2, 3};
Integer [] integers = INTS; / * Compile time error * / 2. Methods in the wrapping class cannot be invoked to the basic type of expression. Such an application will be completely refused by the compiler:
Listing 24: No way, there is no way
INT i = 1;
BYTE B =
I.Bytevalue (); / * Error error * /
8. NULL conversion problem
The reference type in Java can have a special value - "null". Trying to perform auto-unboxing operations to null can cause a "nullpointerexception".
For example, this code will throw an exception at runtime, although it will behave very normal during compilation:
Listing 25: On the surface, just ordinary assignment
Integer
i =
NULL;
INT j =
i; / * Runtime error * /
This is because this code is actually equivalent to:
Listing 26: In fact, it is attempting to call NULL
Integer
i =
NULL;
INT j =
I.intValue (); / * Runtime error * /
The method attempting to call NULL is a behavior that is not recognized by the virtual machine.
If you don't remember the relevant rules
Most offended the codes that use the "Autoboxing / Auto-Unboxing" mechanism, they need to comply with the constraints, will cause compilation errors. Therefore, even if it is not accurately remembered the relevant rules, it is not difficult to find, correctly. Only when it is violated the limitations of "AUTO-UNBOXING operation", it is particularly careful when it is runtime.
9. Influence on overload
Java supports the mechanism for "overload", allowing different methods that have many names that have many names as the same class. Then, the compiler is selected to perform which one to perform according to the argument when the call is called.
The introduction of the autoboxing / auto-unboxing mechanism has slightly adding some factors to consider when this choice - because there may be a method, there is only one version that accepts an Integer type parameter, and one can accept an int The version of the type of parameters, and the Autoboxing / Auto-Unboxing mechanism can automatically convert the arguments between these two types, and the two are difficult to pay. However, because there are both of these two versions of practice, it is not possible to give a compilation error of "Reference TO-called Method IS Ambiguous" to shirk responsibility. This requires an additional new judgment rule.
This new rule is that you don't need to perform autoBoxing / auto-unboxing, take priority to the version of AutoBoxing / Auto-Unboxing.
Therefore, in this case which one is chosen, what type is initially initially selected.
Listing 27: No use of autoboxing / auto-unboxing priority
Public class overloadingtest
{
Private static void testoverloading
INT i) {
System.out.println ("INT");
}
Private static void testoverloading
Integer i) {
System.out.println ("Integer");
}
Public static void main (string [] args)
{
INT i = 1;
Integer J = New Integer (1);
TestoverLoading
i); / * Output "int" * /
TestoverLoading
j); / * Output "integer" * /
}
}
10. Value equivalent and references are equal in Java language, there are two different "equal" concepts - value equal and reference. This has a question of "two values equal to the basic type of data, after autoboxing, the reference to the object is classified".
In "JSR 201: Extending The Java Programming Language with Enumeration, Autoboxing, Enhanced for Loops and Static Import", this issue is made such a regulation:
If the value p Being Boxed is true, false, a byte, an ascii character, or anarch or short number between -127 and ten Case That R1 == R2.
This means that this answer may be "yes" or "no", determined by the type and value of Autoboxing data. Therefore, when detecting whether the two objects represent the same value, it is still necessary to call the equals () method.
However, in J2SDK 1.5 beta 1 and the actual situation in Beta 2, and this is slightly inserted, "Autobox is obtained after the same object reference" is reduced:
Listing 28: The original value is equal, the reference may be equal after autoboxing, or may not wait
Boolean b = true;
Boolean
B1 = B;
Boolean
B2 = B;
System.out.println (
B1 == B2); / * Output "
True "* /
CHAR C = '1';
Character
C1 = C;
Character
C2 = C;
System.out.println (
C1 == C2); / * Output "
False "* /
11. Obstruction of performance
Since the essence of the Autoboxing mechanism is "Automatic creation of the object represents the basic type of basic type data", it is inevitable that there will be some hindrances for performance.
If you just use the autoboxing / auto-unboxing mechanism to save basic types of data (for example, put basic types of data into Collection), this effect is overlooked, because this is just automating the original work that needs to be manually. However, if it is frequent to assign a parcel variable to a parcel variable, this overhead is easy to rise to the extent to which you need.
Note When using the " " and "-" operator of the parcel class, the new object is created instead of modifying the status of the original object.
Listing 29: Is the replacement is not a modification
Integer i = new integer (1);
Integer
J = i; / * Let J, i point to the same object * /
System.out.println (
j == i); / * Currently J, I is the same object, so output "true" * /
i ;
System.out.println (
j == i); / * Now j, i is different objects, so output "false" * /
System.out.println (i); / * Now i's value is "2" * /
System.out.println (j); / * and J value is still "1" * /
This phenomenon is caused by the wrapping classes in Java, "IMMUTABLE" - that is not to provide a way to change the value of the value represented. When you need a lot of assignment operation, you can reduce performance in terms of performance by appropriately using some basic types of local variables. However, if performance bottlenecks are frequently placed in a container, I am afraid I have to rely on the container class designed to accommodate basic types of data (such as Jarkata Commons Primitives components). Those provided).
Listing 30: Program that requires a basic type of data that needs to be placed in a container
Import java.util. *;
Public class wordcounter {
Public static void main (String [] args) {
Hashmap counts = new hashmap ();
For (int i = 0; i String current = args [i]; IF (counts.containskey (current)) { Counts.put (Current, (Integer) counts.get (current)) 1); } else { Counts.put (Current, 1); } } Iterator itR = counts.keyset (). iterator (); itr.hasnext ();) { String key = (string) ITR.NEXT (); System.out.println (KEY ":" counts.get (key)); } } } 12. Summary With the Autoboxing / Auto-Unboxing mechanism provided in J2SE 1.5, you can use a simpler way to solve some of the inconvenients caused by both types of type systems. However, this mechanism does not solve all related problems, some work still needs to be handled by manual operation. In addition, since inappropriate use of this mechanism can cause some negative impact on performance, pay attention to some problems when using. Reference resource You can find the SDK of the J2SE 1.5 and its documentation by Sun's Java Technology page. The latest version is currently J2SDK 1.5 Beta 2. Note When using this version of Javac, add "-Source 1.5" as a parameter to compile the source code for the new language characteristics in J2SE 1.5. John Zukowski introduced how to start using J2SDK 1.5 basics in "Tam Tiger: Tiger Preview". However, this article is written in accordance with the status of J2SDK 1.5 Alpha version, so some details (such as download address and default installation path) have changed. "JSR 201: Extending The Java Programming Language with Enumeration, Autoboxing, Enhanced for Loops and Static Import" The new language features in J2SE 1.5 are defined in J2SE 1.5, including autoboxing / auto-unboxing mechanism, although in headings I only use autoboxing abbreviation. Bruce Eckel In "C #, Java and Joshua Bloch" discloses some messages about the relationship between J2SE 1.5 new language features and C #. Gilad Bracha, James Gosling, Bill Joy and Guy Steele In the "Overloading" section in the "Classes" in the "The Java Language Specification, 2nd Edition" chapter "Method Invocation Expressions" in the "Expression" chapter In the section, the problem of overloading is discussed in-depth. However, this book is written in accordance with the status of the J2SDK version 1.2, so there is no intact cover the actual situation in J2SE 1.5. A set of container classes that specifically to save basic types of data are available in Jakarta Commons Primitives components. And use Java Collection Framework and Autoboxing / Auto-Unboxing to complete the same task, they have more advantages over performance. revise history August 11, 2004 Fix all known errors. Added a background information about the "autoboxing / auto-unboxing" feature. Added some instructions on the "autoboxing / auto-unboxing" feature increase how much the rules that need to be remembered. July 29, 2004 Originally published.