包装类以及128陷阱

本文介绍了Java中的包装类,包括概念、自动拆装箱、128陷阱及其原因。当基本类型在(-128, 127)范围内时,通过valueOf方法创建的Integer对象会复用缓存,导致==比较返回true,超出此范围则会实例化新对象,比较返回false。为避免这个问题,建议使用equals()方法进行对象的相等性判断。" 130070489,10043765,Autosar WdgM模块故障注入与调试实践,"['autosar', '嵌入式', '软件复位', '故障定位', '调试技术']

包装类

概念

基本类型不是对象(不需要在堆中开辟空间)

把基本类型包装一下,具备了原始存储各类类型数据的能力之外,额外的能力,比如不同种类类型之间的转换

基本类型包装类
byteByte
charCharacter
shortShort
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean

包装类的基本操作(以Integer为例)

image-20220516164705421

1.int转Integer new Integer()

int a =10;
Integer a_p =new Integer(a);

2.Integer转int Integer 对象.xxxValue()

image-20220516165307759

Integer a_p =new Integer(4);
int a = a_p.intValue();

3.Integer转String Integer 对象.toString()

Integer a_p =new Integer(4);
String a = a_p.toString();

4.String转Integer(只能是存数字才可以转换,否则编译没错,运行会报错) new Integer

String a ="123";
Integer b = new Integer(a);

5.int转String String.valueOf(a)

int a =10;
String b = String.valueOf(a);

String转int Integer.parseInt(a)

String a ="123";
int b = Integer.parseInt(a);
自动拆装箱(AutoBoxing)
拆装箱

装箱:把基本类型转成对象包装类型

方式一: Integer a =Integer.valueOf(20),

方式二:Integer a =new Integer(20)

拆箱:把包装类型转成对应基本类型

方式一:Integer a =new Integer(20)

方式二:int a_i=a.intValue()

java 5前:拆装箱是需要手动进行的,java 5之后,可以自动完成

自动拆装箱(AutoBoxing)

自动装箱:把一个基本类型变量直接赋值给对应的包装类型

自动拆箱:把一个包装类型变量直接赋值给对应的基本类型

Integer d = 10;//自动装箱 Integer b = Integer.valueOf(10);
int e = d;     //自动拆箱  int e = d.intValue
例子
public class Test {
    public static void main(String[] args) {
        Integer num1=100;
        Integer num2=100;
        Integer num3=new Integer(100);
        Integer num4=new Integer(100);
        Integer num5=200;
        Integer num6=200;
        System.out.println(num1==num2);
        System.out.println(num3==num4);
        System.out.println(num5==num6);
    }
}

image-20220516173035855

Integer num3=new Integer(100);
Integer num4=new Integer(100);

相当于实例化两个对象,对象的值为他们在堆中开辟的空间地址,即使他们的空间又都指向100的地址。==比较的就是值。所以不等。

Integer num1=100;
Integer num2=100;
Integer num5=200;
Integer num6=200;

Integer num1=100;相当于使用了Integer.valueOf方法。之所以会存在前两个相等,后两个不等的情况发生,是因为128陷阱(-128到127)

128陷阱

想要知道128陷阱的原理,要从源码角度出发

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);
}

其使用了IntegerCache类的变量,我们再看看IntegerCache的代码

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() {}
}

不难看出,low和hign的取值为-128和127。

再回到valueOf的方法可以知道,如果值在(-128,127)之间,已经在缓存中创建了对象,会返回cache数组,而数组的地址不变,所以解释了num1==num2的结果是true

如果值不再区间内,会新实例化一个Integer的对象,而对象在堆中开辟的空间是不同的,所以解释了num5==num6的结果是false

解决方法

可以使用Integer的equals()方法来判断相等

public class Test {
    public static void main(String[] args) {
        Integer num5=200;
        Integer num6=200;
        System.out.println(num5==num6);
        System.out.println(num5.equals(num6));
    }
}

image-20220516175730214

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值