虽然JDK8已推出有些日子了,或许等它普及还需些日子。因此这里仍是讨论JDK6和JDK7下String类的substring(int beginIndex ,int endIndex)的使用区别。该方法返回字符串的一个子集,返回的是从原字符串的beginIndex到endIndex-1之间的内容。
先了解在JDK6和JDK7中String类的一个构造:此处省略源代码中异常处理的部分
//JDK6下的String类其中一个构造
/**
* @param value 字符数组的值
* @param offset 数组的偏移量
* @param count 字符数组的长度
*/
public String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
return new String(offset + beginIndex, endIndex - beginIndex, value);
}
//JDK7下的String类构造
public String(char value[], int offset, int count) {
this.value = Arrays.copyOfRange(value, offset, offset + count);
}
public String substring(int beginIndex, int endIndex) {
int subLen = endIndex - beginIndex;
return new String(value, beginIndex, subLen);
}
对于代码:
String str = "abcde"; //创建一个String类对象str
str = str.substring(2,4); //从源字符串截取索引为2到3(4-1)的子字符串
System.out.println(str);
输出结果:cd
对于JDK6,substring(2,4)并未创建一个新的对象,而是仅仅把offset和length修改了指向"cd",而原来的”abe“依然还存在于java堆中,该堆仍被str指向,因此不会被GC回收,导致浪费空间,降低性能。解决方式:让str成为新的对象指向另一空间,只须:str = str.substring(2,4)+"";多加""便可实现新对象的创建。
对于JDK7,从源代码可看出,是通过新生成对象再经拷贝得出,则之前的"abcde"没有被指向而被GC回收。
无图无真相,附自制简图一张帮助理解。