Java中的128陷阱和new String(“xxx“)创建了几个对象问题

1、String str = new String("abc") 创建了几个字符串对象?

答案:1个或者2个

  • 如果字符串常量池中已经有"abc"存在,这种情况只需要新建 1 个对象,即 new 一个对象放在堆中。
  • 当字符串常量池中没有 "abc",此时会创建如下 2 个对象:
    • 一个是字符串字变量 "abc" 所对应的、驻留(intern)在字符串常量池中的实例,字符串常量池只存放实例对象的引用。
    • 另一个是通过 new String() 创建并初始化的,内容与"abc"相同的实例,在堆中。

总结: new String("xxx"); 如果字符串常量池intern中没有对应的xxx 那么就需要在字符串常量池新建,然后再在堆上new 一个对象。


2、String str1 = “abc” 和 String str2 = new String(“abc”)的区别?

两者看似都是创建了一个字符串对象,但在内存中却是不一样的:

  • String str1= “abc” 在编译期,JVM 会去字符串常量池来查找是否存在“abc”如果不存在,就在字符串常量池中开辟一个空间来存储“abc”如果存在,就不用新开辟空间。然后在栈内存中开辟一个名字为 str1 的空间,来存储 “abc” 在常量池中的地址值。
  • String str2 = new String("abc") 在编译阶段 JVM 先去字符串常量池中查找是否存在 “abc”如果过不存在,则在常量池中开辟一个空间存储 “abc”。在运行时期,通过 String 类的构造器在堆内存中 new 了一个空间,然后字符串常量池中的 “abc”复制一份存放到空间中,在中为 str2 开辟空间,存放堆中 new 出来的这个 String 对象的地址值。
  • 也就是说,前者在初始化的时候可能创建了一个对象,也可能一个对象也没有创建;后者因为 new 关键字,至少在内存中创建了一个对象,也有可能是两个对象。

3、Java中的128陷阱?

先来看一个例子:

public static void main(String[] args) {
        Integer a=127,b=127;
        Integer c=128,d=128;
        System.out.println(a==b);// true
        System.out.println(c==d);// false
}

为什么出现这种情况呢?

  • 我们都知道Integer 是 基本类型int 的包装类型。
  • 在Java设计之初,设计者认为,开发者可能经常用到的数字范围都在100以内,而每次使用这些数字的包装类型都要开辟新空间的话,可能会占用大量的资源。
  • 因此他们规定在-128~127之间的Integer类型的变量,直接指向常量池中的缓存地址,不再使用new去开辟出新的空间。

执行 Integer c = 128,相当于执行:Integer c = Integer.valueOf(128),基本类型自动转换为包装类的过程称为,自动装箱(autoboxing)。
这也是出现上述代码两次比较结果不同的原因!下面我们看下valueOf() 源码去体会下:

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

Integer 中引入了 IntegerCache 来缓存一定范围的值,默认情况下范围为:-128~127
因此:上述代码中的 127 命中了 IntegerCache,所以 a 和 b 是相同对象,而 128 则没有命中,所以 c 和 d 是不同对象。

那么,如果想要正确比较的话c与d的话,就需要拆箱比较,即在变量后加intValue()方法:

public static void main(String[] args) {
        Integer a=127,b=127;
        Integer c=128,d=128;
        System.out.println(a==b);// true
        System.out.println(c.intValue()==d.intValue());// true
}

可以直接记住下面的表格,道理都是一样的:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路 飞

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值