Do you really know boxing and unboxing it?

What is boxing and unboxing

In a C ++ programmer seems, Java, many nouns listening to the tall, very simple but in reality, packing and unpacking even worse. By definition the boxing and unboxing: Packing refers to the conversion of primitive type type into packaging, unpacking means to convert the type of wrapper to the base data.

There are eight basic data types Java byte / char / boolean / short / int / long / float / double. In the Java world everything is an object, of course, ultimately, their object package type Byte / Char / Boolean / Short / Integer / Long / Float / Double. With a picture expressing their relationship the most simple:

From the perspective of code, boxing and unboxing Sample Code 1 demonstrates as follows:

public class BoxTest {
    public static void main(String[] args) {
        Long objectLong100 = 100L;
        long baseLong100 = objectLong100;
    }
}
复制代码

Wherein Long objectLong100 = 100L;for binning 100L and assigned to a Long object type variable objectLong100, similarly long baseLong100 = objectLong100;to unpack and objectLong100 were assigned to the basic type variable baseLong100.

Automatic boxing and unboxing

What is the automatic boxing and unboxing

Code can be seen from Examples 1 to convert between types and substantially automatic packaging types. The code with javap decompile byte code can be seen as follows:

As can be seen from the bytecode, the sample code compiler 1 is rewritten into the following form:

public class BoxTest {
    public static void main(String[] args) {
        Long objectLong100 = Long.valueOf(100L);
        long baseLong100 = objectLong100.longValue();
    }
}
复制代码

This is one of Java syntax sugar (sugar, there are many Java syntax, refer to " Hollis original | do not understand this 12 syntactic sugar, not to mention you'll Java " --- automatic packing and unpacking, it eliminates the need for programmers use code conversion is performed between the display type and packing type base.

When the automatic boxing and unboxing

Autoboxing relatively simple scenario: the time assigned to the basic types of packaging types, assignment here is not necessarily = / - = / + = symbol, you can be a method call will trigger automatic packing. as follows:

public class BoxTest {

    public static void main(String[] args) {
        //= 赋值自动装箱
        Long objectLong = 100L;

        //equals 调用自动装箱
        if (objectLong.equals(100L)) {
            System.out.println("objectLong.equals(100L)");
        }
        
        //add 方法调用自动装箱
        List<Long> objectLongList = new ArrayList<>();
        objectLongList.add(objectLong);
    }
}
复制代码

Similarly, when the assignment package types to the basic types of auto-unboxing occur:

public class BoxTest {

    public static void unpacking(long var) {
        System.out.println("var = " + var);
    }
    
    public static void main(String[] args) {
        Long objectLong = 100L;

        //= 赋值自动拆箱
        long basicLong = objectLong;

        //方法调用自动拆箱
        unpacking(objectLong);
    }
}
复制代码

But different automatic packing, unpacking will occur automatically in the following cases:

1, between the package when the package type or types and primitive types for performing mathematical operations (+, -, *, /, +, -, etc.) when.

2, when the base between the package and the types Type ==,! = Comparison operation time.

Where 1 is well understood, after all, math (think CPU operation) can not only be carried out between the objects between basic types. 2 will be briefly described an example:

public class BoxTest {

    public static void main(String[] args) {

        Long objectLong = 500L;
        long basicLong = 500L;

        if (objectLong == basicLong) {
            System.out.println("objectLong == basicLong");
        } else {
            System.out.println("objectLong != basicLong");
        }
    }
}
复制代码

Perform output objectLong == basicLong, which is compared between the basic types and packaging types, unpacking operation occurs, the output is equal. If you still think that basicLong be boxed into packaging type and then compared with objectLong, you would be wrong .

Automatic boxing and unboxing of the "trap"

Automatic boxing and unboxing Dafa is good, but where there is also a lot of "trap", hear me boils, one by one. Look at a piece of code:

public class BoxTest {
    public static void main(String[] args) {

        Long objectLong1 = new Long(10);
        Long objectLong2 = new Long(10);

        Long objectLong11 = 10L;
        Long objectLong22 = 10L;

        Long objectLong5 = 1000L;
        Long objectLong6 = 1000L;

        Long objectLong3 = new Long(10);
        long basicLong = 10L;
        
        if(objectLong1 == objectLong2) {
            System.out.println("objectLong1 == objectLong2");
        } else {
            System.out.println("objectLong1 != objectLong2");
        }

        if(objectLong11 == objectLong22) {
            System.out.println("objectLong11 == objectLong22");
        } else {
            System.out.println("objectLong11 != objectLong22");
        }

        if(objectLong5 == objectLong6) {
            System.out.println("objectLong1 == objectLong2");
        } else {
            System.out.println("objectLong1 != objectLong2");
        }

        if (objectLong3 == basicLong) {
            System.out.println("objectLong3 == basicLong");
        } else {
            System.out.println("objectLong3 != basicLong");
        }
    }
}
复制代码

Use a pen to write down what you think the output of the result, look at the following screenshot of the output I see you "execution" wrong . Results are as follows:

1, the comparison objectLong1 and objectLong2 of nothing else, because they are two package types variables. Because they are not the same object, so it was not equal.

2, according to Comparison objectLong3 with basicLong automated boxing and unboxing when unpacking the mentioned scene may be understood quickly.

3, objectLong5 objectLong6 comparison with the majority of people still not equal to the reasoning: objectLong5 objectLong6 occurred and to automatically packing wrapper objects, == Comparison between two objects are not equal. But the comparison with the output objectLong11 objectLong22 probably make a lot of people stunned. So the way we look at the Long called when autoboxing Long.valueOf(long value)source code:

public final class Long extends Number implements Comparable<Long> {
    //......此处省略一堆
    private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int I = 0; I < cache.length; I++)
                cache[I] = new Long(I - 128);
        }
    }
    //......此处省略一堆
    public static Long valueOf(long l) {
        final int offset = 128;
        if (l >= -128 && l <= 127) { // will cache
            return LongCache.cache[(int)l + offset];
        }
        return new Long(l);
    }
    //......此处省略一堆
}
复制代码

Can be seen that when the value of the basic types of automatic packing time between [-128 to 127], and directly returns LongCache cached objects, and LongCache.cache is an array, which holds a value of -128 wrapper object 127 is allocated at the time of loading the first Long.class. This explains why 10L automatic packing into two objects are equal between them. 1000L and not automatic packing into two equal objects. The former is used for the same object in the cache LongCache.cache, which are new every time autoboxing a new object.

Other package types are used when packing a similar caching method, preventing the formation of too many objects, the Float and Double exception. Automatic packing methods roughly divided into the following three:

  • Be exhaustive, as Byte / Character / Boolean, all cached objects possible values. Therefore, a comparison between the wrapper object of all their same values ​​are equal, and most of the comparison is not equal. Uncertain.
  • Discontinuous non-exhaustive, such as Short / Integer / Long, only the common value of the object cache in the range, comparison between the wrapper object the same value all their portions are equal.
  • Enumeration and not continuous, such as Float / Double, each new packing is a new object.

Interested can click through to view the wrapper class source code, it is relatively simple.

SUMMARY AND RECOMMENDATIONS

1, when the package is essentially a type of the object, automatically packing the first new object in the heap, then the value assigned to the basic types of object value.

2, must not use == /! = Between the package types, comparison is made between the wrapper and the basic types. Please use the equals method , it does not guarantee always correct.

3, when the math, encounters packaging types will be automatically unpack, and then the basic types of operations .

Guess you like

Origin juejin.im/post/5d1610ae6fb9a07eba2c511d