原文链接:https://www.programcreek.com/2013/09/the-substring-method-in-jdk-6-and-jdk-7/
在JDK 6和JDK 7中substring(int beginIndex,int endIndex)的实现是不同的,下面将会做出详细的解释。为简单起见,substring()方法表示的substring(int beginIndex,int endIndex)在这篇文章中的方法。
1.substring()方法
substring(int beginIndex,int endIndex)方法的返回值是,从beginIndex开始到endIndex-1结束的字符串.
String x = "abcdef"; x = x.substring(1,3); System.out.println(x);
输出结果:
bc
2.执行substring()的时候底层的运行机制是什么?
你可能知道,字符串x是不可变的,当x执行subtring(1,3)方法时候,返回值指向了一个新的字符串。如下图所示:
然而,这个图表并不完全正确。JDK 6和JDK 7在执行substring()究竟发生了什么呢?
3.substring()方法在JDK6中的使用。
字符串后端是char数组形式保存的。在JDK 6中,字符串包含3个字段:char value[],int offset,int count。它们用于存储真正的字符数组、数组的第一个索引、字符串中的字符数。
当substring()方法被调用时,它将创建一个新字符串,字符串的值但仍然指向堆中的同一个数组。两个字符串之间的差值是它们的计数和偏移值。
下面的代码简化了,只包含解释这个问题的关键点:
//JDK 6 String(int offset, int count, char value[]) { this.value = value; this.offset = offset; this.count = count; } public String substring(int beginIndex, int endIndex) { //check boundary return new String(offset + beginIndex, endIndex - beginIndex, value); }
4.一个在JDK 6 substring()引发的问题。
如果你有一个很长的字符串,但是你只需要一小部分,每次用substring()。这会导致性能问题,因为你只需要一小部分,你就保留整个事情。JDK 6,解决的办法是使用以下,这将使它指向一个真正的子串:
x = x.substring(x, y) + ""
5.substring()方法在JDK7中的使用。
这是在JDK 7的改进。JDK 7中的方法,substring()实际上创建在堆一个新的数组
//JDK 7 public String(char value[], int offset, int count) { //check boundary this.value = Arrays.copyOfRange(value, offset, offset + count); } public String substring(int beginIndex, int endIndex) { //check boundary int subLen = endIndex - beginIndex; return new String(value, beginIndex, subLen); }