Automatic packing and unloading

Keywords: Programming Java JDK jvm

Java provides eight basic data types, each of which has its corresponding packaging type. The packaging class is an object-oriented class and a high-level data type. It can carry out some more complex operations. They are reference type instead of basic type.

Corresponding relationship between basic type and packaging type
Basic types Packaging type
Byte (1 byte) Byte
short (2 bytes) Short
int (4 bytes) Integer
long (8 bytes) Long
float (4 bytes) Float
double (8 bytes) Double
char (2 bytes) Character
boolean (1 byte) Boolean

 

Automatic boxing
Automatic boxing, in short, automatically wraps basic data types into reference types.

Before JDK 1.5, it was impossible to assign a basic type directly to a reference type. If a reference type was needed, it was necessary to create an object as follows:

        Integer integer = new Integer(10);

After JDK 1.5, they can be converted freely as follows:

        int j = 20;
        Integer integer1 = j;

JVM automatically wraps the basic type j as the reference type Integer, which is the automatic boxing; check its class file, as follows:

    int j = 20;
    
    Integer integer1 = Integer.valueOf(j);

As you can see, automatic boxing is achieved by calling the valueOf() method.

Auto-unboxing

Auto-unboxing is the automatic conversion of a reference type to a basic type, as follows:

        Integer integer = new Integer(10);
        int i = integer;

Decompiles its class file as follows:

    Integer integer = new Integer(10);
    int i = integer.intValue();

As you can see, automatic unboxing is achieved by calling the intValue() method.

The complete code is as follows:

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

        Integer integer = new Integer(10);
        int i = integer;

        int j = 20;
        Integer integer1 = j;
    }
}

The decompiled class file is as follows:

public class Hello
{
  public static void main(String[] args)
  {
    Integer integer = new Integer(10);
    int i = integer.intValue();
    
    int j = 20;
    Integer integer1 = Integer.valueOf(j);
  }
}

 

It is also important to note that when the valueOf() method is called, by default, if the value to be converted is between - 128 and 127, it will be fetched directly from the cache instead of creating an Integer object. The source code is as follows:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

Next, look at its static internal class IntegerCache, which loads when it is first used. As mentioned above, by default, it reads from the cache between - 128 and 127. This maximum value 127 is configurable. It is configurable through the virtual machine parameter - XX: AutoBox CacheMax= < size>, and its source code is as follows:

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {

                }
            }
            high = h;
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            assert IntegerCache.high >= 127;
        }
        private IntegerCache() {}
    }

Next, verify that:

By default:

        Integer i1 = Integer.valueOf(-20);
        Integer i2 = Integer.valueOf(-20);
        System.out.println(i1 == i2); // true

        Integer i3 = Integer.valueOf(20);
        Integer i4 = Integer.valueOf(20);
        System.out.println(i3 == i4); // true

        Integer i5 = Integer.valueOf(127);
        Integer i6 = Integer.valueOf(127);
        System.out.println(i5 == i6); // true

        Integer i7 = Integer.valueOf(-129);
        Integer i8 = Integer.valueOf(-129);
        System.out.println(i7 == i8); // false

        Integer i9 = Integer.valueOf(128);
        Integer i10 = Integer.valueOf(128);
        System.out.println(i9 == i10); // false

As you can see, in addition to - 128 - 127, new objects are created and read from the cache between them.

Next, modify the upper limit by adding the virtual machine parameter - XX: AutoBox CacheMax = < size > to set the upper limit to 200.

Use cases in operation:

        Integer i1 = Integer.valueOf(128);
        Integer i2 = Integer.valueOf(128);
        System.out.println(i1 == i2); // true

        Integer i3 = Integer.valueOf(200);
        Integer i4 = Integer.valueOf(200);
        System.out.println(i3 == i4); // true

        Integer i5 = Integer.valueOf(201);
        Integer i6 = Integer.valueOf(201);
        System.out.println(i5 == i6); // false

As you can see, the upper limit has changed.

Integer, Short, Byte, Character, Long's valueOf methods are the same as above, from - 128 to 127 from the cache fetch.

Double, Float is not, because the number of integer values in a range is limited, while floating-point numbers are not.

        Double l1 = Double.valueOf(100.0);
        Double l2 = Double.valueOf(100.0);
        System.out.println(l1 == l2); //false

        Double l3 = Double.valueOf(200.0);
        Double l4 = Double.valueOf(200.0);
        System.out.println(l3 == l4);//false

Their valueOf methods are as follows:

    public static Double valueOf(double d) {
        return new Double(d);
    }

    public static Float valueOf(String s) throws NumberFormatException {
        return new Float(parseFloat(s));
    }

What about the Boolean type?

       Boolean b1 = Boolean.valueOf(true);
       Boolean b2 = Boolean.valueOf(true);
       System.out.println(b1 == b2);//true

       Boolean b3 = Boolean.valueOf(false);
       Boolean b4 = Boolean.valueOf(false);
       System.out.println(b3 == b4);//true

Its source code is as follows:

    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);

    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

As you can see, they point to the same static object.

summary

1. Autoboxing: Automatically converting basic classes to reference types, calling the valueOf() method implementation

2. Auto-unboxing: Auto-converting reference type to basic type, calling intValue() method implementation

3.valueOf() method: Integer, Short, Byte, Character, Long's valueOf() method, in a certain range of values directly from the cache, and will not create objects, only beyond the boundaries will create objects. Double, Float's valueOf() method creates new objects each time, because the number of floating-point numbers is infinite within a certain range. The valueOf() method of the Boolean object calls the same static object.

Posted by kof20012 on Tue, 29 Jan 2019 04:36:15 -0800