I. What is automatic packing and unpacking
Very simple, the following two lines of code can see the boxing and unpacking process
1 // Automatic Boxing 2 Integer total =; 3 4 // self-setting unpacking 5 int Totalprim = total;
Simply put, boxing is the automatic conversion of the base data type to the wrapper type; unpacking is the automatic conversion of the wrapper type to the base data type.
Let's take a look at the types of crates that need to be boxed:
This process is performed automatically, so we need to look at its execution process:
1 Public class Main {2 void Main (string[] args) {3 // Automatic Boxing 4 Integer total =; 5 6 // self-setting unpacking 7 int Totalprim = Total ; 8 }9 }
After you decompile the class file, you get the following:
1 javap-c stringtest
Integer total = 99;
Executing the code above, the system executes for us:
Integer total = integer.valueof (99);
int totalprim = total;
Executing the code above, the system executes for us:
int totalprim = Total.intvalue ();
Let's take an example of integer to analyze its source code:
1, first look at the integer.valueof function
1 Public Static Integer valueOf (int i) {2return new Integer (i): Small_values[i + ]; 3 }
It will first determine the size of I: If I is less than-128 or greater than or equal to 128, create an integer object, otherwise execute Small_values[i + 128].
First, let's look at the constructor of the integer:
1 Private Final intvalue;2 3 PublicInteger (intvalue) {4 This. Value =value;5 }6 7 PublicInteger (String string)throwsNumberFormatException {8 This(parseint (String));9}
It defines a value variable, creates an integer object, and initializes the variable. The second passed in is a string variable, which first converts it to an int value and then initializes it.
Here's a look at what Small_values[i + 128] is:
1privatestaticfinalnew integer[256];
It is a static integer array object, which means that eventually valueof returns an integer object.
So we can summarize here: the process of boxing will create the corresponding object, this will consume memory, so the boxing process will increase memory consumption, affect performance.
2. Then look at the Intvalue function
1 @Override 2 Public int intvalue () {3 return value; 4 }
This is simple, return the value directly.
Ii. related issues
Above we see in the constructor of integer, it is divided into two cases:
1, I >= 128 | | I < -128 =====> new Integer (i)
2, I < && i >= -128 =====> small_values[i + 128]
1 Private Static Final New INTEGER[256];
Small_values had already been created, that is to say, in I >= 128 | | I < 128 is to create a different object, at I < Max && I >=-128 will return the specified object that has been created based on the value of I.
This may not be clear enough, let's give an example:
1 Public classMain {2 Public Static voidMain (string[] args) {3 4Integer i1 = 100;5Integer i2 = 100;6Integer i3 = 200;7Integer I4 = 200;8 9System.out.println (I1==I2);//trueTenSystem.out.println (I3==I4);//false One } A}
After the code, we can see that the results of their execution are not the same, why, look at the instructions above us.
1, I1 and I2 will be automatically boxed, execute the valueof function, their values in (-128,128] This range, they will get the small_values array inside the same object small_values[228], They refer to the same integer object, so they must be equal.
2, i3 and I4 will also be automatically boxed, the valueof function is executed, their values are greater than 128, so the new Integer (200) will be executed, that is, they will create two different objects, so they must not be equal.
Let's take a look at another example:
1 Public classMain {2 Public Static voidMain (string[] args) {3 4Double I1 = 100.0;5Double i2 = 100.0;6Double i3 = 200.0;7Double I4 = 200.0;8 9System.out.println (I1==I2);//falseTenSystem.out.println (I3==I4);//false One } A}
Look at the above results, unlike the integer, it is not surprising, because their valueof implementation is different, the results are certainly different, then why they do not unify it?
This is very well understood, because for integer, there is only a fixed 256 value between (-128,128), so in order to avoid creating objects more than once, we have created an integer array small_values of good one size 256 in advance, so if the value is within this range, You can simply return to our pre-created object.
However, for double types, we cannot do this because the number is infinite within this range.
The sum is: the number of integer values within a range is limited, but the floating-point numbers are not.
So in double it is straightforward to create an object directly, so each object created is not the same.
1 Public Static Double valueOf (double d) {2 returnnew double (d); 3 }
Let's do a collation:
The integer faction: integer, Short, Byte, Character, long are similar to the implementations of the valueof methods of these classes.
Double factions: the implementation of the ValueOf method of double and float is similar. Each time a different object is returned.
The following is a summary of the integer factions, such as:
Let's take a look at another scenario:
1 Public classMain {2 Public Static voidMain (string[] args) {3 4Boolean I1 =false;5Boolean i2 =false;6Boolean i3 =true;7Boolean I4 =true;8 9System.out.println (I1==I2);//trueTenSystem.out.println (I3==I4);//true One } A}
You can see that all returned are true, that is, they do valueof return the same object.
1 Public Static Boolean ValueOf (boolean b) {2 return b? Boolean.TRUE:Boolean.FALSE; 3 }
You can see that it does not create an object because two objects have been created in advance, because there are only two cases, which is also to avoid creating too many objects repeatedly.
1 Public Static Final New Boolean (true); 2 3 Public Static Final New Boolean (false);
There are a couple of things that are introduced here, and the rest of the situation is discussed below.
1 Integer num1 =n; 2 int num2 =n; 3 // true
Description NUM1 = = Num2 carried out unpacking operation
1 Integer num1 = +; 2 int num2 = +; 3 System.out.println (Num1.equals (num2)); // true
Let's look at the equals source code first:
1 @Override 2 Public Boolean equals (Object o) {3 return instanceof Integer) && ((integer) o). Value = = value); 4 }
We specify that equal compares the content itself, and we can also see that the equal parameter is an object, and we pass in an int type, so boxing first, then comparing, returns True because it compares the value inside the object.
1 Integer num1 = +; 2 int num2 = +; 3 Long num3 = 200l; 4 System.out.println (NUM1 + num2); // $ 5 System.out.println (num3 = = (Num1 + num2)); // true 6 System.out.println (num3.equals (NUM1 + num2)); // false
1. When an underlying data type is associated with a package class = =, + 、-、 *,/, the wrapper class is disassembled and the underlying data type is calculated.
2, for Num3.equals (NUM1 + num2) for the reason of false is very simple, we still according to the code implementation to illustrate:
1 @Override 2 Public Boolean equals (Object o) {3 return instanceof Long) && ((Long) o). Value = = value); 4 }
It must meet two conditions before it is true:
1, the same type
2. Same content
The reason for returning false above is that the type is different.
1 Integer num1 = +; 2 Ingeger num2 =; 3 Long num3 = 300l; 4 // true
Let's decompile some of this class file: Javap-c stringtest
When you can see the operation, the NUM3 is first disassembled (execution of the num3 Longvalue gets the value 300 of the underlying type long), The NUM1 and mum2 are then disassembled (the intvalue of NUM1 and num2, respectively, are given the values 100 and 200 of the base type int), and then the underlying operations are related.
Let's take a test of the underlying type:
1 int num1 = +; 2 int num2 =N; 3 long mum3 = +; 4 // true
It explains why the top will return true.
Therefore, when the two operands of the "= =" operator are references to the wrapper type, the comparison is to whether the same object is being compared, and if one of the operands is an expression (that is, it contains arithmetic operations), the value is compared (that is, the process that triggers the automatic unboxing).
Trap 1:
1 Integer integer100=null; 2 int int100=integer100;
These two lines of code are completely legal and can be compiled completely, but at run time, a null pointer exception is thrown. Where integer100 is an integer-type object, it can of course point to null. However, on the second line, the integer100 is disassembled, that is, executing the Intvalue () method on a null object, and of course throwing a null pointer exception. Therefore, it is important to pay special attention to whether the encapsulated class object is null when there is a unboxing operation.
Summarize:
1, need to know when will trigger boxing and unpacking
2, boxing operations will create objects, frequent boxing operations will consume a lot of memory, affect performance, so you can avoid boxing should try to avoid.
3, Equals (Object O) because the parameter type in the original Equals method is the package type, the passed parameter type (a) is the original data type, so it is automatically boxed and, conversely, it is unboxing
4, when the two different types with = = comparison, the wrapper class needs to be dismantled, when the same type with = = comparison, will automatically remove the box or packing
Detailed Java automatic packing and unpacking (autoboxing and unboxing)