String a=new String(“aa“) 创建了几个对象?

本文探讨了Java中创建String对象的情况,特别是`String a=new String("aa")`会创建两个对象,一个在堆中,一个在字符串常量池。`new String("a") + new String("b")`则会创建六个对象,包括StringBuilder和多个String实例。在JDK7以后,由于元空间的变化,`intern()`方法的行为发生了改变,可能导致意外的引用结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

String

拼接

字符串的拼接分为两种情况:

  • 字面量的拼接
    编译器优化,直接视为拼接后的结果

  • 存在变量的拼接

    实际调用的是StringBuilder
    不在存储在StringPool中而是直接在堆中创建新的String实例。

String a=new String(“aa”) 创建了几个对象?

创建了两个,因为new在堆空间中创建了一个,并且在字符串常量池中也创建了一个。

new String(“a”) + new String(“b”) 创建了几个对象?

创建了六个对象

  1. 第一个对象是StringBuilder
  2. new
  3. 字符串常量池中的"a"
  4. 同上
  5. 同上
  6. 在由StringBuilder完成字符串变量拼接完成后返回的 toString()方法中还会创建一个新的对象

值得注意的是在后面这个问题中并没有在字符串常量池中新建字符串常量 “ab”

@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}

再继续上面的问题

String a=new String("1")+new String("1");
a.intern();
String b="11";
System.out.println(a==b);

输出的其实是true。

  1. 变量a指向堆空间中的字符串对象的实例
  2. a执行intern方法将字符串"11"加入到字符串常量池中,返回的字符串常量池中字符串常量的地址无变量接收
  3. 变量b指向字符串常量池中的字符串常量"11"

看似没什么问题应该输出false。但是实际输出true的原因是:

  1. 在jdk7及以后由于放弃了永久代的概念改为了元空间,并且将字符串常量池存储在了堆中
  2. 变量a调用intern方法时,由于StringPool和变量a同处于堆中,jvm进行了空间的优化,不再在字符串常量池中创建字符串常量,而是在字符串常量池中添加了变量a的引用。
  3. 变量b确实是在字符串常量池中找到了字面量,但是其内容其实是堆空间中实例的引用。
  4. 值得注意的是,实例a调用的intern方法至关重要,如果不执行,返回的就是false,变量b的创建和以前一样在字符串常量池中找不到"11"的字面量,故此新建一个并返回。想想其实也合理,毕竟若不是实例直接调用intern方法时方便获得实例的引用,jvm总不能在每一个字符串添加进常量池之前都在偌大的堆空间中找找有没有相同内容的字符串。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值