分享下我的印象笔记~~
1、substring()函数的功能?
当一个String对象调用substring(int beginIndex,int endIndex)函数时,返回一个以 beginIdex 开始并以 endIndx-1 结束的String对象。String内部表示形式是char[] 。
code:
@Test
public void testSubstring(){
String str = "abcedf";
System.out.println(str.substring(1,3));
}
public void testSubstring(){
String str = "abcedf";
System.out.println(str.substring(1,3));
}
OUTPUT:
bc
2、当substring函数被调用时,内存中发生的事情?
正如你所知道的,String对象是不可变的. 当str = str.substring(...)被调用时,内存中会分配一块新的内存地址存放str对象,此时str会指向 ’bc‘。
但是这并没有非常精确的表现出内存中真正发生的事情。当substring(...)被调用时,JDK6和JDK7内存中处理是不同的。
3、substring() in JDK6
String是支持字符数组的,即char[] 。在JDK6中,String类有4个字段,分别是:
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0
分别被用来 存储一个字符数组,第一个被使用的字符的索引,字符的个数。
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0
分别被用来 存储一个字符数组,第一个被使用的字符的索引,字符的个数。
当substring被调用时,创建一个新的String对象,但是字符串值(string's value)依旧指向内存中的同一个字符数组char varry。不同的是 两个String对象的 偏移量offset 和 字符个数 count。
'abcedf'对象和 'bc'对象指向的是同一个 char[] 即:[abcedf],也就是说对象 “abced”并不会被GC回收。JDK6中的源代码:
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
this.value = value;
this.offset = offset;
this.count = count;
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
new String(offset + beginIndex, endIndex - beginIndex, value);
}
4、JDK6引发的问题
如果有一个 Very long 字符串,但是每次只需要调用substring()函数截取非常小的一部分字符串,这会造成一个性能问题.以后每次只需要 a small part , but keep a whole thing.
In JDK6 , 有一个解决方案,创建一个新的对象使他指向真实的sub string.
x = x.string(1,3)+"";
现在 x 对象中的value 指向了 数组 [b,c];
5、 substring() in JDK7
这个问题在JDK7中得到了改善,substring() 函数会在内存中真实的创建一个新的char[] 。
JDK7 source code :
//JDK 7public 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);
6、Arrays.copyOfRange函数内部
Arrays.copyOfRange函数内部创建了一个新的数组 char[] copy = new char[newLength]; Arrays.copyOfRange 源代码:
public static char[] copyOfRange(char[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
char[] copy = new char[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}