java核心基础---基本数据类型的包装类

一.什么是包装类

众所周知,java是一门面向对象的语言,java中,有8种基本数据类型,这8种基本类型似乎不符合java面向对象的特点。为了保证java中“一切皆对象”的原则,java给每一个基本类型都分别整了一个类对这8种基本数据类型进行包装,这就是包装类。

二.八个基本数据类型的包装类

基本数据类型 --- 包装类

byte --- Byte   short --- Short     int --- Integer     long --- Long 

float --- Float   double --- Double  char --- Character   boolean --- Boolean

三.包装类的装箱和拆箱

装箱:将基本数据类型变为包装类,每个包装类的构造方法都可以接收各自数据类型的变量

拆箱:将包装类转换为基本数据类型,就是从包装类中取出被包装的数据

自动拆箱和自动装箱:就是指拆箱和装箱操作都是自动执行的

根据上述可知,基本数据类型和包装类是可以进行相互转换的

我们来看这样一行代码:

Integer a = 10;
//在这行代码中,就进行了自动装箱
//这行代码在执行的时候在jvm中会编写为Integer a = Integer.valueOf(10);
//将10这一基本数据类型转换为了包装类,赋值给b

int a = b;
//这一行代码中,进行了自动拆箱,将包装类的b转换为基本类型int,赋值给了a

四.128陷阱

什么是128陷阱?我们先来看这样一段代码:

Integer a = 100;
Integer b = 100;
System.out.println(a==b);
		
Integer a1 = 128;
Integer b1 = 128;
System.out.println(a1==b1);

这段代码输出为第一行:true  第二行:false

为什么呢?这就需要我们去看底层代码,上面我们说到 Integer a = 100;实际是在执行Integer a = Integer.valueOf(100); 我们去看看这个Integer中的valueOf();方法是怎么写的:

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

这段代码的意思就是,当我传入的int类型的参数,大于一个最小值且小于一个最大值的时候,直接返回一个值,当不在这个区间范围内的时候,就需要在堆内存中new一个新的内存空间。

当值在最小值和最大值之间的时候返回的东西到底是什么呢?这个最大值和最小值又是多少呢?我们来深挖一下,这里我们把返回值中的IntegerCache的源码搬来看看:

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

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

            // Load IntegerCache.archivedCache from archive, if possible
            CDS.initializeFromArchive(IntegerCache.class);
            int size = (high - low) + 1;

            // Use the archived cache if it exists and is large enough
            if (archivedCache == null || size > archivedCache.length) {
                Integer[] c = new Integer[size];
                int j = low;
                for(int i = 0; i < c.length; i++) {
                    c[i] = new Integer(j++);
                }
                archivedCache = c;
            }
            cache = archivedCache;
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

这段代码完整的看下来可能也是云里雾里,我们只需要看懂一部分就行了,首先这个最大值和最小值很容易就能找得到,最大值是127,最小值是128,返回的那个cache数组我们只需要看上述代码截取的这一段代码:

int size = (high - low) + 1;          
if (archivedCache == null || size > archivedCache.length) {
    Integer[] c = new Integer[size];
    int j = low;
    for(int i = 0; i < c.length; i++) {
        c[i] = new Integer(j++);
    }
    archivedCache = c;
}
cache = archivedCache;

嘿,这段代码不就是给这个数组进行初始化吗,很难不看出这就是一个长度为256的,存储着-128到127的数组。

这一切都解释得清了,答案就在Integer的valueOf()方法之中,如果我们传入的数值在-128到127之间,都会存储在一个cache数组之中,这个数组就相当于一个缓存,当我们在-128到127之间进行自动填箱的时候,我们就直接返回cache数组之中这个数所在的地址,因此我们刚开始的 Integer a = 100;Integer b = 100;中,a和b存储的地址是相同的,输出true。但是如果传进的参数不在这个范围之内的话,就需要在堆内存中开辟一个新的内存空间,因此Integer a1 = 128;Integer b1 = 128;中,a1和b1存储的地址就是不同的,输出是false。

五.包装类小练习

看一看下面代码的输出结果:

		int a = 100;
		int b = 100;
		Integer a1 = 100;
		Integer b1 = 100;
		Integer a2 = new Integer(100);
		Integer b2 = new Integer(100);
		System.out.println("1:"+ (a==b));
		System.out.println("2:"+ (a1==b1));
		System.out.println("3:"+ (a2==b2));
		System.out.println("4:"+ (a1==a));
		System.out.println("5:"+ (a1.equals(a)));
		System.out.println("6:"+ (a1==a2));
		System.out.println("7:"+ (a==a2));

输出结果为:

解释:1.第一行不需要进行解释

2.第二行中100是在-128到127之间的数,因此a1和b1存储的都是cache数组中100的地址,是相同的,返回值为true。

3.第三行中a2和b2都是各自在堆内存中开辟了一块新地址,两块地址肯定是不同的,返回值为false。

4.第四行中 包装类用 == 和基本数据类型进行比较的时候会自动拆箱,就相当于两个int类型相比较,返回值自然为true。

5.第五行中 a1.equals();方法需要传入一个Object类型的数据,因此a会进行自动装箱,这里我们把Integer.equals方法的源码搬来看一看,value值相等就返回true,因此返回值为true。

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

6.第六行中 a1中存储的地址是cache数组中100的地址,a2中存储的地址是在堆内存中开辟的内存的地址,两个地址肯定不同,故返回值为false。

7.第七行中 a2会进行自动拆箱,转换为两个基本数据类型int相比,返回值为true。

  • 34
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值