函数substring(int beginIndex, int endIndex)在jdk1.6和jdk1.7中是不一样的。理解其中的原理可以让我们更好的使用Java的API。
1、首先看一下substring函数的功能。
substring
(int beginIndex, int endIndex)
函数返回字符串由beginIndex开始到endIndex-1的子串。
String <span style="font-family:SimHei;">x</span>="<span style="font-family:SimHei;">abcdef</span>";
<span style="font-family:SimHei;">x</span> = <span style="font-family:SimHei;">x</span>.substring(1,<span style="font-family:SimHei;">3</span>);
System.out.println(<span style="font-family:SimHei;">x</span>);
打印:el
2、当调用substring方法时,内存中是怎么来处理的
由于String类型是final类型的所以当调用substring并赋值时,实际上abc指向了一个新的内存地址。
上图描述可能不是很精准,但是基本上可以看到内存中的处理。
3、substring在jdk1.6中
String在内存中是以数组的形式来存储的,在jdk1.6中String类型包括三个属性,char[]value,offset,count,char数组引用,起始位置,字符长度。
在上面代码的例子中实际是由两个String的实例,这两个实例引用了heap中同一个字符数组。
//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);
}
但是这样会有一个问题就是,如果有个很长的字符串但是substring后只用其中的两个字符,这样也会一直引用整个字符数组,这样就会造成内存浪费。jdk1.6中可以通过如下方法解决。
x = x.subtring(1,3) + "";
4、substring在jdk1.7中的处理
subtring在jdk1.7中的处理,会根据子字符串在heap中创建新的char[],并且将String引用指向新创建的字符串数字。
<span style="font-size:14px;"> //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);
}</span>