Detailed text in a Java unpacking and packing operation

First, what is the automatic boxing and unboxing:

We know that java eight basic types provides a corresponding packaging type, respectively, before the Java SE5, if you want to generate a value to an Integer object 10 must be so:

Integer i=new Integer(10);

In the Java SE5 begins by providing automatic packing characteristics, if a value to be generated for the Integer object 10, so that it need only:

Integer i=10;

This process automatically creates an Integer object depending on the type of value, it is automatically boxed, empathy

Integer i=10;int j=i;

The above code is automatically unpacking automatically unpacking to an int Integer object

Packing simply is the automatic basic data types into type packaging, unpacking the package type is automatically converted to the base type

Second, boxing and unboxing is how to achieve:

java process valueOf packing wrapper class method calls implemented, while unpacking process is performed (corresponding to the basic type represents xxx) xxxValue method call wrapper class implementation
needs what type of boxing and unboxing:
Here Insert Picture Description
Here Insert Picture Description
This process is automatically execution, then we need to look at its implementation process:

public class Main {
    public static void main(String[] args) {
    //自动装箱
    Integer total = 99;

    //自定拆箱
    int totalprim = total;
    }
}

After decompile class file to get the following:
Here Insert Picture Description
Integer Total = 99;
execution sentence above code, we have implemented systems:
Integer Total = Integer.valueOf (99);

int totalprim = total;
executing the above sentence code, we perform the system:
int = totalprim total.intValue ();

We are now at Integer, for example, to analyze its source:
1, first take a look at Integer.valueOf function

 public static Integer valueOf(int i) {
 return  i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
 }

It first determines the size of i: if i is greater than or equal to 128 -128, an Integer object is created, otherwise SMALL_VALUES [i + 128].

首先我们来看看Integer的构造函数:

private final int value;

public Integer(int value) {
    this.value = value;
}

public Integer(String string) throws NumberFormatException {
    this(parseInt(string));
}

它里面定义了一个value变量,创建一个Integer对象,就会给这个变量初始化。第二个传入的是一个String变量,它会先把它转换成一个int值,然后进行初始化。
下面看看SMALL_VALUES[i + 128]是什么东西:

private static final Integer[] SMALL_VALUES = new Integer[256];
它是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象。

所以我们这里可以总结一点:装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。
所以在Integer的构造函数中,它分两种情况:

1、i >= 128 || i < -128 =====> new Integer(i)
2、i < 128 && i >= -128 =====> SMALL_VALUES[i + 128]
2、接着看看intValue函数

 @Override
 public int intValue() {
    return value;
 }

这个很简单,直接返回value值即可。

例子:

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

        Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;

        System.out.println(i1==i2);  //true
        System.out.println(i3==i4);  //false
    }
}

代码的后面,我们可以看到它们的执行结果是不一样的,为什么,在看看我们上面的说明。
1、i1和i2会进行自动装箱,执行了valueOf函数,它们的值在(-128,128]这个范围内,它们会拿到SMALL_VALUES数组里面的同一个对象SMALL_VALUES[228],它们引用到了同一个Integer对象,所以它们肯定是相等的。

2、i3和i4也会进行自动装箱,执行了valueOf函数,它们的值大于128,所以会执行new Integer(200),也就是说它们会分别创建两个不同的对象,所以它们肯定不等。
下面我们来看看另外一个例子:

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

        Double i1 = 100.0;
        Double i2 = 100.0;
        Double i3 = 200.0;
        Double i4 = 200.0;

        System.out.println(i1==i2); //false
        System.out.println(i3==i4); //false
    }
}

看看上面的执行结果,跟Integer不一样,这样也不必奇怪,因为它们的valueOf实现不一样,结果肯定不一样,那为什么它们不统一一下呢?
这个很好理解,因为对于Integer,在(-128,128]之间只有固定的256个值,所以为了避免多次创建对象,我们事先就创建好一个大小为256的Integer数组SMALL_VALUES,所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。

但是对于Double类型来说,我们就不能这样做,因为它在这个范围内个数是无限的。
总结一句就是:在某个范围内的整型数值的个数是有限的,而浮点数却不是。

所以在Double里面的做法很直接,就是直接创建一个对象,所以每次创建的对象都不一样。

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

下面我们进行一个归类:
Integer派别:Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double派别:Double、Float的valueOf方法的实现是类似的。每次都返回不同的对象。

下面对Integer派别进行一个总结,如下图:
Here Insert Picture Description
下面我们来看看另外一种情况:

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

        Boolean i1 = false;
        Boolean i2 = false;
        Boolean i3 = true;
        Boolean i4 = true;

        System.out.println(i1==i2);//true
        System.out.println(i3==i4);//true
    }
}

可以看到返回的都是true,也就是它们执行valueOf返回的都是相同的对象。

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

可以看到它并没有创建对象,因为在内部已经提前创建好两个对象,因为它只有两种情况,这样也是为了避免重复创建太多的对象。

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

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

三、进一步讨论其他情况

上面把几种情况都介绍到了,下面来进一步讨论其他情况。

Integer num1 = 400;  
int num2 = 400;  
System.out.println(num1 == num2); //true

说明num1 == num2进行了拆箱操作,会将num1执行intValue操作再进行比较

Integer num1 = 100;  
int num2 = 100;  
System.out.println(num1.equals(num2));  //true

我们先来看看equals源码:

 public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

我们指定equal比较的是内容本身,并且我们也可以看到equal的参数是一个Object对象,我们传入的是一个int类型,所以首先会将num2进行装箱成Integer,然后比较,比较的时候再将其拆箱intValue比较,之所以返回true,是由于它比较的是对象里面的value值。

 Integer num1 = 100;  
 int num2 = 100;  
 Long num3 = 200L;  
 System.out.println(num1 + num2);  //200
 System.out.println(num3 == (num1 + num2));  //true
 System.out.println(num3.equals(num1 + num2));  //false

1、当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
2、对于num3.equals(num1 + num2)为false的原因很简单,我们还是根据代码实现来说明:

@Override
 public boolean equals(Object o) {
  return (o instanceof Long) && (((Long) o).value == value);
 }

equals它必须满足两个条件才为true, 而==不用,会拆箱对基础类型进行运算
1、类型相同
2、内容相同
上面返回false的原因就是类型不同。

 Integer num1 = 100;
 Ingeger num2 = 200;
 Long num3 = 300L;
System.out.println(num3 == (num1 + num2)); //true

我们来反编译一些这个class文件:javap -c StringTest
Here Insert Picture Description
可以看到运算的时候首先对num3进行拆箱(执行num3的longValue得到基础类型为long的值300),然后对num1和mum2进行拆箱(分别执行了num1和num2的intValue得到基础类型为int的值100和200),然后进行相关的基础运算。

我们来对基础类型进行一个测试:

 int num1 = 100;
 int num2 = 200;
 long mum3 = 300;
 System.out.println(num3 == (num1 + num2)); //true

就说明了为什么最上面会返回true.

所以,当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。

陷阱1:

1  Integer integer100=null;  
2  int int100=integer100;

这两行代码是完全合法的,完全能够通过编译的,但是在运行时,就会抛出空指针异常。其中,integer100为Integer类型的对象,它当然可以指向null。但在第二行时,就会对integer100进行拆箱,也就是对一个null对象执行intValue()方法,当然会抛出空指针异常。所以,有拆箱操作时一定要特别注意封装类对象是否为null。

总结

1、需要知道什么时候会引发装箱和拆箱
2、装箱操作会创建对象,频繁的装箱操作会消耗许多内存,影响性能,所以可以避免装箱的时候应该尽量避免。
3、equals(Object o) 因为原equals方法中的参数类型是封装类型,所传入的参数类型(a)是原始数据类型,所以会自动对其装箱,反之,会对其进行拆箱
4、当两种不同类型用= = 比较时,包装器类的需要拆箱, 当同种类型用==比较时,会自动拆箱或者装箱
5.装箱就是执行valueof方法创建integer对象,在-128-127会直接返回cache的常量,其他范围会创建新的对象;自动将基本数据类型转换为包装器类型;
6.= =(或者其他算术类型的运算时)在两个Integer进行比较的时候,首先判断是不是在缓存池中,是则相等
在一个Integer 一个int时,Integer会进行拆箱,所以Integer a=400 = = int a=400
equals比较时,要同时比较内容value和类型!

其他

1, turn Integer i = new Integer (xxx) and Integer i = xxx; the difference between the two approaches.
1) The first method does not trigger automatic packing process; and the second way is triggered. Automatic packing (valueOf) get the value from the cache
2) and differences in the efficiency of resource utilization. The second way the efficiency and resources occupied in the general case is better than the first case (note that this is not absolute).
2, equals the same type, the content is the same, the cache will be used packing -128-127
Here Insert Picture Description
128 exceeds 127 will automatically use new Integer embodiment, it is equal to
Here Insert Picture Description

3, Integeri = 1; i + = 1; do what things?
First Integer i = 1; do autoboxing (using Integer.valueOf () method of the type Integer packing int), then i + = 1; i first type Integer to automatically unpack int (using Integer.intValue () method of unpacking Integer int), i running again after the completion of the addition into the packing type Integer.
4,
Here Insert Picture Description

Reference article:
https://www.cnblogs.com/wang-yaz/p/8516151.html

Published 107 original articles · won praise 14 · views 40000 +

Guess you like

Origin blog.csdn.net/belongtocode/article/details/102967678