了解String.substring的原理

Honey ·
更新时间:2024-09-21
· 743 次阅读

文章目录1.首先我们要了解String对象放入常量池的时机验证2.substring返回时究竟发生了什么操作JDK1.6中的substringJDK1.6中的substring中产生的问题JDK1.7中的substring 1.首先我们要了解String对象放入常量池的时机

String只会在一种情况下放入常量池,那就是用""修饰时。
例如

String str1 = "abc";

这个时候会把字符串"abc"放入常量池。
又或者当编译器可以确定变量的值时,如下:

String str1 = "abc" + "def";

这个时候会把字符串"abcdef"放入常量池。

所以我们得出一个结论substring返回值是不会保存在常量池中的,所以他会随着GC调用而回收

验证 public static void main(String[] args) throws InterruptedException { String a = "123456"; String b = a.substring(3); System.out.println(System.identityHashCode(b.intern())); b = null; System.gc(); b = a.substring(3); System.out.println(System.identityHashCode(b.intern())); b = null; System.gc(); b = a.substring(3); System.out.println(System.identityHashCode(b.intern())); // 输出结果 // 1804094807 // 951007336 // 2001049719 } 2.substring返回时究竟发生了什么操作 JDK1.6中的substring

JDK1.6中String对象由以下3个成员变量组成

String(int offset, int count, char value[]) { this.value = value; this.offset = offset; this.count = count; } value char数组 offset 偏移量 count 长度

所以在JDK1.6中substring本质上是生成一个新的String对象,但是引用的char数组是和父对象是同一个数组,只是改变了偏移量与长度

public String substring(int beginIndex, int endIndex) { if (beginIndex count) { throw new StringIndexOutOfBoundsException(endIndex); } if (beginIndex > endIndex) { throw new StringIndexOutOfBoundsException(endIndex - beginIndex); } return ((beginIndex == 0) && (endIndex == count)) ? this : new String(offset + beginIndex, endIndex - beginIndex, value); } JDK1.6中的substring中产生的问题

既然没有数组还是同一个数组,那么在回收大字符串的时候会因为剪切过的字符串还在引用,而导致无法回收,从而引起内存泄漏。这个BUG也被官方收录并在JDK1.7中得到了修正。
原创文章 47获赞 42访问量 8万+ 关注 私信 展开阅读全文
作者:加班狂魔



substring string

需要 登录 后方可回复, 如果你还没有账号请 注册新账号