关于String 的创建与内存存储

本文详细介绍了Java中String的创建方式(字面量和构造器),内存存储(常量池和堆内存),以及字面量的懒加载特性、拼接优化和intern()方法的作用。特别强调了1.7版本后字符串常量池的变化以及如何影响内存使用。

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

关于String 的创建与内存存储

字符串常量池(String Pool,也称 String Table),在 JDK1.7 之前存放在方法区内,在 JDK1.7 及之后版本,字符串常量池的位置更改到了堆内存中。
Java8内存结构

String的创建方式:

  1. 构造器:通过new的方式创建
  2. 字面量:通过这种方式创建:String a = “字面量方式创建的字符串”;

但是无论哪种方式创建,其实都是使用一个char数组进行存储。
String的存储方式
虽然存储方式都是char数组,但是由于创建方式不同,在细节上也会有所不同。

构造器方式创建:

使用构造器创建字符串对象的过程和创建其他对象完全相同,就是直接在堆中创建一个对象,然后将该对象的引用返回,变量就会存储该变量的引用,即对象的内存地址。
但是需要注意,使用已有字符串对象创建时,新字符串对象的value熟悉和已有字符串对象的value属性是相同的,即执行同一个char数组。
构造器创建字符串-使用已有字符串创建对象

字面量

通过字面量创建字符串时,需要考虑字符串常量池。
字符串常量池位于堆中(只针对1.7以后版本),是一个由C++实现的HashTable,键是由字符串字面量及长度计算得到的Hash值,值为字符串对象的直接引用。
借助字符串常量池,可以减少字面量相同的字符串对象的创建,节省内存空间
使用字面量创建字符串对象时,会首先检查字符串常量池中有没有相同的键,如果有则直接返回,如果没有,则再堆中新建一个字符串对象,将其相关的Hash值与直接引用存入字符串常量池中。

字面量特点
  1. 非对象
    严格的数,字面量在代码运行到它所在语句前,它还不是字符串对象
    字面量的创建
  2. 懒加载
    当第一次使用到字面量的时候,才会创建对应的字符串对象。
  3. 不重复
    同一个类中的值相同的字面量,其实只有一份,因为【类文件常量池】包括【运行时常量池】都是以类为单位的,所以不同类中相同字面量在内存中会存有两份,但是由于字符串常量池的存在,只要字面量相同,字符串对象也相同。
构造器+字面量

当同事使用构造器+字面量创建字符串时,会同事在堆中创建两个字符串对象,其中一个是根据字面量创建的,而另一个是通过构造器创建的,两个对象是不同的。

String s4 = "def";
String s5 = new String("def");
System.out.println(s4 == s5); // false

拼接
字面量拼接

使用字面量拼接时,编译时会进行优化,实际上是使用字面量进行构造。

String s6 = "abcedf";
String s7 = "abc" + "edf";  // 实质上就是  String s7 = "abcedf";
System.out.println(s6 == s7); // true

引用拼接

使用引用拼接时,实际上是新建了一个StringBuilder对象,调用append方法进行拼接,最后嗲偶哦那个toString方法创建一个新的String对象

String s8 = "123456";
String s9 = "123";
String s10 = s9 + "456";
System.out.println(s8 == s10); // false

但是,如果引用的变量使用了final修饰,则又相当于字面量拼接。

String s8 = "123456";
final String s9 = "123";
String s10 = s9 + "456";
System.out.println(s8 == s10); // true

intern()

使用intern()方法可以查询字符串常量池中是否存在字面量相同的字符串。

  • 如果存在,则返回此字符串的对象引用;
  • 如果不存在,则将此对象的引用放入字符串常量池中,并返回此引用(始终只有一个对象)。
String x = new String(new char[]{'a', 'b', 'c'});
String y = "abc"; // 通过字面量构造,"abc"对应对象的引用加入 String Table
String z = x.intern(); // 已有,返回 String Table 中 "abc" 对应对象的引用
System.out.println(z == y);  // true
System.out.println(z == x);  // false

参考博客:https://blog.youkuaiyun.com/x326279579/article/details/132208682

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值