In this article, I would like to introduce a very important and interesting feature in Java, that is, automatic boxing and unboxing, and from the source code to interpret the principle of automatic boxing and unboxing, and this feature also left a trap. Developers can easily fall into this trap if they don't pay attention.
Automatic Boxing (autoboxing)
Defined
When you write Java programs in peacetime, you often define an integer object in the following ways:
Integer i=100;
As you can see from the above code, I is an integer reference, and 100 is the underlying data type in Java (primitive). The practice of directly passing an underlying data type to its corresponding encapsulation Class (wrapper class) is automatic boxing (autoboxing).
In JDK 1.5, automatic boxing was introduced for the first time. Before JDK 1.5, if you want to define an integer object of value 100, you need to do this:
Integer i=new integer (100);
Principle
We are in the above code "Integer i=100;" Place a breakpoint and follow it.
Next, we can see that the program jumps to the valueof (int i) method of the integer class
/**
* Returns A <tt>Integer</tt> instance representing the specified
* <tt>int</tt> Value.
* If A new <tt>Integer</tt> instance is isn't required, this method
* should generally being used in preference
to the constructor * {@link #Integer (int)}, as it is likely to yield
* significantly better spaces and TI Me performance by caching
* frequently requested values.
*
* @param i <code>int</code> value.
* @return A <tt>Integer</tt> instance representing <tt>i</tt>
* @since 1.5 */public
static Integer valueof (int i) {
if (i >= -128 && i <= integercache.high ) return
Integercache.cache[i + 128];
else return the
new Integer (i);
}
In other words, boxing is the JDK's own help for you to complete the call integer.valueof (100).
Unpacking box (unboxing)
Defined
Integer integer100=100;
int int100=integer100;
From the above code, you can see that integer100 is a reference of an integer type, int100 is the original data type of an int type. However, we can assign an object of an integer type to a variable of its corresponding original data type. This is the unboxing.
Unboxing and boxing are the opposite operations. Boxing is a variable that assigns an original data type to the corresponding encapsulated class. A unboxing is a variable that assigns a variable of a encapsulated class to the corresponding original data type. The name of the box and the unboxing is also quite appropriate.
Principle
I believe we all guessed, the process of unpacking the JDK for us to do what. Let's go through the experiment to prove our conjecture.
In the second line of code above, break the breakpoint, that is, in "int int100=integer100;" Hit the breakpoint and follow up.
We can see that the program jumps to the integer Intvalue () method.
/**
* Returns The value of this <code>Integer</code> as a
* <CODE>INT</CODE>.
*
/public int intvalue () {return
value;
}
That is, the JDK has helped us to complete the call to the Intvalue () method. For the above experiment, it is the Intvalue () method that invokes integer100, which assigns the return value to int100.
Extended
Experiment 1
Integer integer400=400;
int int400=400;
System.out.println (integer400==int400);
In the third line of the above code, integer400 and int400 execute the = = run. And these two are different types of variables, in the end is integer400 unboxing, or int400 box it? What is the result of the operation?
The = = operation is to determine whether the address of two objects is equal or to determine whether the values of two underlying data types are equal. Therefore, it is easy to speculate that if the integer400, then the comparison is the two underlying types of values, which is necessarily equal at this time, the result is true, if the int400 boxed, the comparison is two objects of the address is equal, that at this time the address is necessarily unequal, The run result is false. (As for why the author assigns them to 400, which is related to the traps to be mentioned later).
We actually run the result to true. So it's integer400 unpacking. This is also evidenced by the results of code tracking.
Experiment 2
Integer integer100=100;
int int100=100;
System.out.println (Integer100.equals (int100));
In the third line of the above code, the argument for integer100 's method equals is int100. We know that the Equals method's argument is object, not the underlying data type, so it must be int100 boxed here. This is also evidenced by the results of code tracking.
In fact, if the parameter type in a method is the original data type, the type of parameter that is passed in is its encapsulated class, and it is automatically disassembled, and, correspondingly, if the parameter type in a method is the encapsulated type and the parameter type passed in is its original data type, it is automatically boxed.
Experiment 3
Integer integer100 = m;
int int100 = m;
Long long200 = 200l;
System.out.println (integer100 + int100);
System.out.println (long200 = = (integer100 + int100));
System.out.println (long200.equals (integer100 + int100));
In the first experiment, we have already learned that when an underlying data type and a wrapper class are performed = = Operations, the encapsulated class is disassembled. What if the + 、-、 *,/What? In this experiment, we will know.
If the + operation, the underlying data type is boxed, then:
• In line 4th, integer100+int100 gets an object o of type integer and value 200, and executes the ToString () method of the object and outputs "200";
• In line 5th, integer100+int100 will get an object of type integer and value 200 to compare this object with the Long200 object, which will obviously output false;
• In line 6th, integer100+int100 will get an object of type integer and value 200 O,long the Equals method will long200 compared with O, because both are different types of encapsulation class, so output false;
If the + operation will remove the encapsulated class, then:
• In line 4th, INTEGER100+INT100 will get a base data type B with type int and value 200, then boxing B to get O, execute the object's ToString () method, and output "200";
• In line 5th, integer100+int100 will get a type int and the value of 200 of the underlying data type b1,== operation will be long200 to the unboxing B2, obviously b1==b2, output true;
• In line 6th, integer100+int100 will get a b,long of the base data type int with value 200, and the Equals method will box B, but the boxing gets the object o with type Integer. Because O and long200 are different types of objects, so output false;
The results of the program running are:
200
True
False
Thus, the second presumption is correct, that is, in the + operation, the encapsulation class will be disassembled.
Trap
Trap 1
Integer Integer100=null;
int int100=integer100;
These two lines of code are completely legitimate and can be compiled completely, but when run, NULL pointer exceptions are thrown. Where, integer100 is an integer type object, it can of course point to null. On the second line, however, the integer100 is split, which means that the Intvalue () method is executed on a null object, which, of course, throws a null pointer exception. Therefore, it is important to pay special attention to whether the encapsulated class object is null if there is a unboxing operation.
Trap 2
Integer i1=100;
Integer i2=100;
Integer i3=300;
Integer i4=300;
System.out.println (I1==I2);
System.out.println (I3==I4);
Because I1, I2, i3, and I4 are all integer types, we think that the results of the operation should all be false. However, the actual result of the operation is "System.out.println (I1==I2);" is true, but "System.out.println (I3==I4);" to False. It also means that I1 and i2 These two integer references point to the same object, and i3 and I4 point to different objects. Why, then? Aren't all calls to the integer.valueof (int i) method?
Let's look at the integer.valueof (int i) method again.
/**
* Returns A <tt>Integer</tt> instance representing the specified
* <tt>int</tt> Value.
* If A new <tt>Integer</tt> instance is isn't required, this method
* should generally being used in preference
to the constructor * {@link #Integer (int)}, as it is likely to yield
* significantly better spaces and TI Me performance by caching
* frequently requested values.
*
* @param i <code>int</code> value.
* @return A <tt>Integer</tt> instance representing <tt>i</tt>
* @since 1.5 */public
static Integer valueof (int i) {
if (i >= -128 && i <= integercache.high ) return
Integercache.cache[i + 128];
else return the
new Integer (i);
}
We can see that when i>=-128 and I<=integercache.high, return directly to Integercache.cache[i + 128]. Where the Integercache is an integer internal static class with the original code as follows:
private static class Integercache {static final int high;
Static final Integer cache[];
static {final int low =-128;
High value May is configured by property int h = 127; if (integercachehighpropvalue!= null) {//Use Long.decode this to avoid invoking methods that//require
Integer ' s autoboxing cache to is initialized int i = Long.decode (integercachehighpropvalue). Intvalue ();
i = Math.max (i, 127);
Maximum array size is integer.max_value h = math.min (i, Integer.max_value--low);
High = h;
cache = new Integer[(high-low) + 1];
int j = Low;
for (int k = 0; k < cache.length; k++) cache[k] = new Integer (j + +); Private Integercache () {}}
We can see clearly that Integercache has a static member variable cache, which is an array of 256 elements. The cache is also initialized in Integercache, where the first element is an integer object with a value of i-128. And-128 to 127 are the most commonly used integer objects, and this is a great way to improve performance. Also because of this, "Integeri1=100;integer i2=100;", I1 and I2 get the same object.
In contrast to the second experiment in the extension, we are told that when the package class and the underlying type are run, the encapsulation class is split, the result of the unpacking is compared to the underlying type, and the two packages are run with the same object as the other objects, comparing the addresses of two objects. It also determines whether two references point to the same object.
This article on the Java Automatic boxing and unboxing and traps are small parts to share all the content, hope to give you a reference, but also hope that we support the cloud habitat community.