自学内容网 自学内容网

基本数据类型和包装类型的区别、缓存池、自动拆箱装箱(面试题)

目录

1. 八种基本类型及对应包装类型

2. 基本类型和包装类型 区别

3. 自动拆箱装箱

3.1 自动装箱

3.2 自动拆箱

3.3 缓存池

4. 高频面试案例分析


1. 八种基本类型及对应包装类型

基本数据类型类型描述范围(指数形式)位数包装类型
byte整型(有符号)-2 ^ 7 ~2 ^ 7 -11字节= 8bitByte
short整型(有符号)-2 ^ 15 ~2 ^ 15 -12字节=16bitShort
int整型(有符号)-2 ^ 31 ~2 ^ 31 -14字节= 32bitInteger
long整型(有符号)-2 ^ 63 ~2 ^ 63 -18字节= 64bitLong
float浮点型1.401298e-45 ~ 3.402823e+38(绝对值)4字节=32bitFloat
double浮点型4.9000000e-324 ~ 1.797693e+308(绝对值)8字节=64bitDouble
char字符型‘\u0000’~’\uFFFF’2字节=16bitCharacter
boolean布尔型只有两个值:true 或 false1字节= 8bitBoolean

2. 基本类型和包装类型 区别

  • 1.性能

基本类型:占用内存小,效率高,适合频繁使用的简单操作。
包装类型:因为是对象,涉及内存分配和垃圾回收,性能相对较低。

  • 2. 存储位置

基本类型:如果是局部变量则保存在栈上面,如果是成员变量则在堆中。
包装类型:保存在堆上(成员变量,在不考虑川IT优化的栈上分配时,都是随着对象一起保存在堆上的)。

  • 3. 初始化方式

基本类型:直接赋值
包装类型:需要采用new的方式创建

  • 4. 比较方式

基本类型:比较用==,直接比较数值。
包装类型:比较时,==比较的是对象的内存地址,而equals()比较的是对象的值。

  • 5. 默认值

基本类型:默认值是0,false 等。
包装类型:默认为null。

3. 自动拆箱装箱

3.1 自动装箱

装箱 :就是将基本数据类型用他们对应的包装类包装起来

Integer i = 10;

我们将上述代码反编译即得到:

Integer i = Integer.valueOf(10);

查看源码可知:

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}
    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) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

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

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
}

在Integer的valueof(int i)中,我们传递进去的参数是基本数据类型int型,在函数内部如上所示利用了Integer内部的一个私有静态类IntegerCache,该类静态初始化了一个包含了Integer.IntegerCache.lowjava.lang.Integer.IntegerCache.high的Integer数组。其中java.lang.Integer.IntegerCache.high的取值范围在[127~Integer.MAX_VALUE - (-low) -1]之间。

在该区间内所有的Integer.valueOf(int)函数返回的对象,是根据int值计算的偏移量,从数组Integer.IntegerCache.cache中获取,返回一个Integer对象。如果不在[IntegerCache.low~IntegerCache.high)之间,就会在JVM中分配内存new一个新的Integer对象。

因此,我们可以看出来装箱的时候其实就是自动调用了Integer的valueOf(int)方法

3.2 自动拆箱

拆箱就是将包装类型转换为基本数据类型

如下:

Integer i = 10;//装箱
int n = i;   //拆箱

反编译得到:

Integer i = Integer.valueOf(10);
int n = i.intValue();

查看源码:

private final int value;
public int intValue() {
    return value;
}

可以看出,在拆箱的时候调用了Integer对象的intValue()方法。包装类在装箱时,将我们传入的int型参数value保存起来且私有不能被改变,在拆箱时利用intValue()方法返回int型的value值。

因此总结一下装箱和拆箱的实现过程就是:

装箱过程是通过调用包装类的valueOf方法实现的,而拆箱过程是通过调用包装类的 xxxValue方法实现的。(xxx代表对应的基本数据类型)。

注意:我们要了解的是,频繁的装箱拆箱的话,会增加内存的消耗,影响性能

  

3.3 缓存池

java中有6个缓存池,基本数据类型的包装类除了 Float 和 Double 之外,其他六个包装器类(Byte、Short、Integer、Long、Character、Boolean)都有常量缓存池

  • Byte:-128~127,也就是所有的 byte 值
  • Short:-128~127
  • Long:-128~127
  • Character:\u0000 - \u007F
  • Boolean:true 和 false

下面详细说一下java中 Integer缓存池

Java的Integer缓存池(IntegerCache)是为了提升性能和节省内存。根据实践发现大部分的数据操作都集中在值比较小的范围,因此缓存这些对象可以减少内存分配和垃圾回收的负担,提升性能

拿 Integer 来举例子

Integer 类内部中内置了 256 个 Integer 类型的缓存数据,当使用的数据范围在 -128~127 之间时会直接返回常量池中数据的引用,而不是创建对象超过这个范围时会创建新的对象。

  • new Integer(100) 每次都会新建一个对象;
  • Integer.valueOf(100) 会使用缓存池中的对象,多次调用只会取同⼀一个对象的引用。

原理:

Java 在自动装箱时,对于值在-128到127之间的int类型,会直接返回一个已经缓存的Integer 对象,而不是创建新的对象。

缓存池的使用场景:

  • 自动装箱(Auto-boxing):当基本类型int转换为包装类Integer时,若数值在缓存范围内,返回缓存对象。

  • 值比较:由于相同范围内的整数使用同一个缓存对象,使用==可以正确比较它们的地址(引用相同),而不需要使用equals()。但是要注意对于超过缓存范围的Integer对象,==比较的是对象引用,而不是数值。要比较数值,应使用equals()方法。

4. 高频面试案例分析

下面这段代码的输出结果是什么呢?

public class Main {
    public static void main(String[] args) {
         
        Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;

        Integer one=new Integer(100);
        Integer two=new Integer(100);

        Integer z = Integer.valueOf(18);
        Integer k = Integer.valueOf(18);
        System.out.println(z == k);//6

        System.out.println(i1==i2);   //1
        System.out.println(i3==i4);   //2    
        System.out.println(one==two);  //3
        System.out.println(i1==100);   //4
        System.out.println(i1==one);   //5


        

    }

提醒:

1.   ”==“用于比较引用和比较基本数据类型时具有不同的功能,具体如下:

  • 基本数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。
  • 引用数据类型:比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。

2. 装箱过程(基本类型转为包装类型)是通过调用包装类的valueOf方法实现的,而拆箱过程(包装类型转为基本类型)是通过调用包装类的 xxxValue方法实现的。(xxx代表对应的基本数据类型);

Integer包装类当使用的数据范围在 -128~127 之间时会直接返回常量池中数据的引用,而不是创建对象超过这个范围时会创建新的对象。

  • new Integer(100) 每次都会新建一个对象;
  • Integer.valueOf(8) 会使用缓存池中的对象,多次调用只会取同⼀一个对象的引用。

解答:

1,true,上面的代码中i1和i2的数值为100,是Integer包装类型且数据范围在 -128~127 之间,因此直接从IntegerCache(Integer缓存池)会直接返回常量池中数据的引用,而不是创建对象,超过这个范围时会创建新的对象。

2,false,这里很多同学容易出错,上面的代码中i3和i4的数值为200,根据IntegerCache私有静态类的源码可以发现,当数值不在[127~Integer.MAX_VALUE - (-low) -1]即[-128,127]之间时,便会创建新的Integer对象。因此这里i3和i4是两个不同对象,因此为false。

3,false,这里就很好理解了,因为new Integer(100);创建了两个不同的对象,==比较的是内存地址。

4,true,这里其实包含两个步骤:① Integer i1 = 100;进行装箱;② i1==100自动进行了拆箱,因此这里是两个基本数据类型进行比较,值必然相同。

i1是一个Integer对象,而100是一个基本类型int的值。在比较Integer对象和基本类型int时,Java会进行自动拆箱,将Integer对象转换成int值进行比较。由于i1实际上是缓存中的对象,它的值是100,所以i1的值(100)和基本类型int的值(100)是相等的,

5,false,i1对象进行了装箱,其是直接从IntegerCache私有静态类的Integer数组中取已经存在的对象。而one是创建了一个新的对象,因此两者的内存地址必然不相同。

6,true,这里调用了valueOf方法 装箱,第一次Integer z = Integer.valueOf(18);会创建 Integer对象值是18(在 -128~127 之间),并且放入Integer缓存池中,第二次Integer k = Integer.valueOf(18);会直接从缓存中返回 值为18的Integer对象的地址值,本质是同一个对象引用,所以z=k,true。

参考:

https://blog.csdn.net/qq_44085437/article/details/124028654


原文地址:https://blog.csdn.net/m0_64422133/article/details/143720442

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!