对intern()的理解

对intern()的理解

intern()的执行逻辑为:
在字符串常量池找和字符串对象的值相等的一个对象或引用 如果找不到,就创建,
如果堆里有找的对象,就创建一个引用,该引用指向堆里要找的对象,并返回该引用 如果堆里没有,就创建一个字符串对象并返回
先看这道题
        String s = new StringBuilder("计算机").append("软件").toString();
        Assert.assertTrue(s.intern() == "计算机软件");
        Assert.assertTrue(s.intern() == s);
        Assert.assertTrue(s == "计算机软件");

运行结果是成功的,2-4行全部为true。这里要注意到intern()的距离含义和逻辑

比如该题的执行逻辑

  1. 第一行在字符串常量池中创建了“计算机” 和 “软件” 这两个对象,最终将s 指向堆中的一个String对象,该对象的value 字段指向的堆中的 “计算机软件” 对象。

  2. 第二行 s .intern() 首先在字符串常量池中找 “计算机软件”,没找到,然后发现堆中有“计算机软件” 这个对象,于是在字符串常量池中创建了一个引用指向该对象,并将该引用返回; “计算机软件”同样在字符串常量池中找,找到了之前的指向“计算机软件” 的引用,也返回,所有 s .intern() == “计算机软件” 结果为true。

  3. 同样s也指向同一个"计算机软件"对象,所以都是true。

要证实这点,还可以再看以下代码

        String s = new StringBuilder("计算机").append("软件").toString();
        // 先执行"计算机软件",会字符串常量池生成一个字符串对象,之后intern返回是字符串对象的引用
        Assert.assertTrue("计算机软件" == s.intern());//true
        Assert.assertTrue(s.intern() == s);//false
        Assert.assertTrue(s == "计算机软件");

当先执行"计算机软件"时,字符串常量池中就创建了"计算机软件"对象,这时intern()返回的就是字符串常量池中的"计算机软件"对象,和s指向的字符串就不是同一个了。

同样成立以下代码

        String s = new StringBuilder("计算机软件").toString();
        Assert.assertTrue(s.intern() == "计算机软件");//true
        Assert.assertTrue(s.intern() == s);//false
<think>好的,我现在需要详细解释一下Java中的intern()方法。首先,我得回忆一下自己对这个方法的理解,可能还需要查阅一些资料来确保准确性。 首先,我知道String在Java中是不可变的,并且有两种创建方式:使用字面量或者new关键字。使用字面量的话,字符串会被放入常量池,而new出来的则是在堆内存中。这时候,intern()方法的作用应该和字符串常量池有关。 那intern()方法具体是做什么的呢?我记得它可能用来将字符串添加到常量池中,或者返回常量池中已有的字符串。比如说,当用new创建一个字符串时,它会在堆中生成一个新的对象,而不是在常量池里。这时候如果调用intern(),可能就会检查常量池是否有相等的字符串,如果有的话就返回那个常量池的引用,否则将这个字符串添加到常量池并返回引用。 不过具体细节可能需要注意。比如在Java的不同版本中,字符串常量池的位置有没有变化?我记得在Java 7之前,常量池是在方法区,而Java 7之后移到了堆内存里。这可能影响intern()方法的行为吗?比如,当调用intern()时,如果是Java 7之后,字符串对象可能直接引用堆中的对象,而不是方法区中的。 然后,举个例子会更好理解。比如,用new创建两个内容相同的字符串对象,它们的引用是不同的,但如果调用了intern(),那么两个intern()返回的引用是否相同?应该相同,因为它们会指向常量池中的同一个字符串。 但是需要注意,如果字符串字面量已经存在于常量池中,那么调用new出来的字符串的intern()方法就会直接返回那个字面量的引用。比如,String s1 = "hello"; String s2 = new String("hello").intern(); 这时候s1和s2应该指向同一个对象。 此外,使用intern()有什么好处和缺点呢?好处可能是节省内存,避免重复创建相同字符串的对象,尤其是处理大量重复字符串时。但缺点可能是常量池的实现可能影响性能,比如如果大量调用intern(),可能会增加常量池的大小,导致GC压力或者性能问题。例如,在Java 6中,常量池在永久代,容易造成OOM,但Java 7之后在堆中,可能缓解了这个问题。 另外,需要说明intern()是Native方法,具体的实现可能依赖JVM版本。所以使用时要谨慎,确保了解其行为。 总结一下,intern()方法的作用是将字符串对象添加到常量池(如果池中没有该字符串),并返回对应的常量池引用。这样不同的字符串对象调用intern()后,可能指向同一个常量池中的实例,从而节省内存。但需要注意潜在的性能影响和版本差异。</think>在 Java 中,`intern()` 是 `String` 类的一个方法,用于操作**字符串常量池**(String Pool)。它的核心作用是:**确保字符串在常量池中唯一存在**,从而优化内存使用和比较效率。 --- ### **工作原理** 1. **当调用 `intern()` 时**: - 如果常量池中已存在与当前字符串内容相同的字符串,则直接返回池中的引用。 - 如果不存在,则将该字符串添加到常量池(或记录其引用,具体行为取决于 JVM 版本),然后返回池中的引用。 2. **常量池的位置**: - **Java 6 及之前**:常量池位于“永久代”(PermGen),易引发内存溢出。 - **Java 7 及之后**:常量池移至堆内存,生命周期与普通对象一致,由垃圾回收管理。 --- ### **示例代码** ```java String s1 = new String("hello"); // 堆中的对象,常量池已存在"hello"(因字面量) String s2 = s1.intern(); // 返回常量池的引用 System.out.println(s1 == s2); // false(s1在堆,s2在池) System.out.println("hello" == s2); // true(均指向池中的"hello") String s3 = new String("world"); // 堆中的对象,常量池尚无"world"(假设首次创建) String s4 = s3.intern(); // 将"world"加入常量池,返回池引用 System.out.println(s3 == s4); // false(s3在堆,s4在池) ``` --- ### **适用场景** 1. **减少重复字符串的内存占用** 适合处理大量内容相同的字符串(如日志处理),通过 `intern()` 共享唯一实例。 2. **加速字符串比较** `==` 比较常量池引用比 `equals()` 更高效,但需确保所有字符串都经过 `intern()` 处理。 --- ### **注意事项** - **性能权衡** 频繁调用 `intern()` 可能导致哈希表查询开销,需结合场景测试。 - **版本兼容性** Java 7+ 的常量池在堆中,允许被垃圾回收,减少内存泄漏风险。 - **慎用于动态字符串** 对动态生成的字符串(如拼接结果)使用 `intern()` 可能导致常量池膨胀。 --- ### **总结** `intern()` 通过复用常量池中的字符串,优化内存和比较效率,但需权衡性能与场景。在需要处理大量重复字符串时,合理使用它可显著提升程序效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值