String和常量池

jdk1.6之前常量池属于永久代,jdk1.7以后移到堆中。

String s1 = "abc";// 放在常量池中
        String s2 = "abc";// 从常量池中查找
        String s3 = new String("abc");//new放在堆中
        String s4 = new String("abc");
        String s5 = s1.intern();
        String s6 = s3.intern();
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s1 == s5);
        System.out.println(s1 == s6);
        System.out.println(s3 == s4);
        System.out.println("==================");
        System.out.println(s1.equals(s2));
        System.out.println(s1.equals(s3));
        System.out.println(s1.equals(s5));
        System.out.println(s3.equals(s4));


==:比较引用地址一样

equals:比较的是两个对象的内容是否一样

当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。


String.intern()方法获得在常量池中的字符串引用,如果常量池中没有则会将字符串加入,然后将该引用放入list持有
确保不会被回收,jdk报错permgem space发生在永久代 jdk7报错 java heap space发生在堆

List<String> list = new ArrayList<>();
        int i = 0;
        while (true) {
            list.add(String.valueOf(i++).intern());
        }


### Java String 常量池的工作原理及作用 #### 工作原理 在 Java 中,`String` 是一种特殊的对象类型,其不可变性常量池机制是为了优化内存使用提升程序性能而设计的。当创建一个 `String` 对象时,如果该字符串已经存在于常量池中,则不会重新分配内存空间来存储相同的值,而是直接返回已存在的引用[^1]。 具体来说,Java 的字符串常量池主要由两部分组成: - **静态常量池**:这是在编译阶段形成的,在 `.class` 文件中有对应的结构表示。 - **运行时常量池**:这是在 JVM 加载类之后形成的一种数据结构,位于方法区内存区域。它不仅包含了静态常量池的内容,还可以动态加入新生成的字符串实例[^4]。 以下是关于字符串常量池的一些关键行为: 1. 当通过字面量方式定义字符串(如 `String str = "abc";`),JVM 会先检查字符串常量池是否存在相同内容的对象。如果存在则重用已有对象;否则将其添加到池中并返回相应引用[^3]。 2. 使用 `new String()` 构造器显式创建字符串时,会在堆上开辟一块独立的空间存放此字符串,并不自动将其实例化版本放入常量池中。因此即使两个变量都指向同一个字面意义上的字符串,它们仍然可能代表不同地址上的实体[^2]。 3. 方法 `intern()` 可以手动干预这一过程——调用某个非池化的字符串实例的 `intern()` 函数后,若发现当前字符串尚未驻留于全局共享表里,则会被复制一份进去供后续查找匹配之需[^4]。 #### 作用 引入字符串常量池的主要目的是为了节省资源消耗以及加速比较操作: - **减少重复占用**: 如果多个地方需要用到完全一致的文字序列表达形式的话,那么只需要保存单一副本即可满足需求. - **加快相等判断速度**: 因为基于引用对比(`==`)要比逐字符逐一核验效率高得多所以只要确认两者确实来自同一份原始资料就足以得出结论. ```java // 示例代码展示 intern() 功能 public class Main { public static void main(String[] args) { String a = new StringBuilder("计算机").append("软件").toString(); System.out.println(a.intern() == a); // 输出 true String b = new StringBuilder("ja").append("va").toString(); System.out.println(b.intern() == b); // 输出 false (因为"java"已经在加载时进入了常量池) } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值