JDK6中的substring()
java中字符串是通过字符数组来支持实现的,在JDK6中,String类包含3个域,char[] value、int offset、int count。分别用于存储真实的字符数组、数组的偏移量,以及String所包含的字符的个数。
当substring()方法被调用的时候,它会创建一个新的字符串对象,但是这个字符串的值在java 堆中仍然指向的是同一个数组,这两个字符串的不同在于他们的count和offset的值。
下面是jdk6中的原代码,是简化后只包含用来说明这个问题的关键代码:
1
2
3
4
5
6
7
8
9
10
11
|
//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); } |
如果你有一个非常长的字符串,但是你仅仅只需要这个字符串的一小部分,这就会导致性能问题(译注:可能会造成内存泄露,这个bug很早以前就有提及),因为你需要的只是很小的部分,而这个子字符串却要包含整个字符数组,在jdk6中解决办法就是使用下面的方法,它会指向一个真正的子字符串。
1
|
x = x.substring(x, y) +
"" |
JDK7中的substring()
在JDK7中有所改进,substring()方法在堆中真正的创建了一个新的数组,当原字符数组没有被引用后就被GC回收了.因此避免了上述问题.
1
2
3
4
5
6
7
8
9
10
11
|
//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); } |