JDK6和JDK7中String的substring()方法
2015-06-19 12:32
531 查看
转自:http://www.programcreek.com/2013/09/the-substring-method-in-jdk-6-and-jdk-7/
参考:http://www.importnew.com/7656.html
http://book.51cto.com/art/201504/472208.htm
JDK6 与JDK7中的 substring(int beginIndex, int endIndex) 方法存在不同。
输出
![](http://img.blog.csdn.net/20150619110442128)
但是,这其实不完全正确。
JDK6 String 主要包括三个部分
调用substring() 方法时,会创建一个新的字符串,但是这个字符串的value 仍然指的堆中的同一个字符数组。这两个字符只是通过 count 和 offset 来区别的。
![](http://img.blog.csdn.net/20150619111441713)
可以看到在 substring()的视线中,使用了String 的构造函数,生成一个新的String。
JDK 6 的String 构造函数:
内存泄露就出现在构造函数中,新生成的String 的value 简单的使用了原 String 的value的引用(value是一个final 数组),只是修改了offset 和count。
当原始字符被回收之后,value中多余的部分就造成了空间浪费。
假设有个很大的字符串而每次只是使用substring() 来使用一小部分。这就会引起性能问题, since you need only a small part, you keep the whole thing.
假设 x=x.substring(1,20) 长度只有19,value数组后面的就用不到,但是value还被引用,无法回收不用的部分。
For JDK 6, the solution is using the following, which will make it point to a real sub string:
![](http://img.blog.csdn.net/20150619120721841)
JDK 7 中对String进行调整,去掉offset 和count 两项,String 的实质性内容仅由value决定,而value数组本身就代表这个String 的实际取值。
这是这种改进,解决了内存泄露的问题。
看到这里的评论中,讲:
实际上是String() 和substring() 两个方法在JDK6,JDK7中的区别,是构造方法的实现变了
所以事实上 JDK6的取子串的方法是有效率的 ,而JDK7中的String(char[],int,int)实现中Arrays.copyOfRange的调用 ,虽是本地方法, 但当字符串很大时还是有效率问题。总之JDK7中区别体现更多的是为了安全,而不是性能。
参考:http://www.importnew.com/7656.html
http://book.51cto.com/art/201504/472208.htm
JDK6 与JDK7中的 substring(int beginIndex, int endIndex) 方法存在不同。
substring作用
substring(int beginIndex, int endIndex) 方法返回一个以beginIndex 开始,endIndex-1 结束的string。String x = "abcdef"; x = x.substring(1,3); System.out.println(x)
输出
bc
What happens when substring() is called
你或许会认为x 被赋值为x.substring(1,3)之后会指向一个新的字符串。但是,这其实不完全正确。
substring() in JDK 6
String其实是一个字符数组。JDK6 String 主要包括三个部分
private final char value[]; private final int offset; private final int count;
调用substring() 方法时,会创建一个新的字符串,但是这个字符串的value 仍然指的堆中的同一个字符数组。这两个字符只是通过 count 和 offset 来区别的。
//JDK 6 public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); }
可以看到在 substring()的视线中,使用了String 的构造函数,生成一个新的String。
JDK 6 的String 构造函数:
String(int offset, int count, char value[]) { this.value = value; this.offset = offset; this.count = count; }
内存泄露就出现在构造函数中,新生成的String 的value 简单的使用了原 String 的value的引用(value是一个final 数组),只是修改了offset 和count。
当原始字符被回收之后,value中多余的部分就造成了空间浪费。
假设有个很大的字符串而每次只是使用substring() 来使用一小部分。这就会引起性能问题, since you need only a small part, you keep the whole thing.
假设 x=x.substring(1,20) 长度只有19,value数组后面的就用不到,但是value还被引用,无法回收不用的部分。
For JDK 6, the solution is using the following, which will make it point to a real sub string:
x = x.substring(x, y) + ""
substring() in JDK 7
JDK 7 中,substring()方法在堆中创建了一个新的数组。//JDK 7 public String substring(int beginIndex, int endIndex) { //check boundary int subLen = endIndex - beginIndex; return new String(value, beginIndex, subLen); }
JDK 7 中对String进行调整,去掉offset 和count 两项,String 的实质性内容仅由value决定,而value数组本身就代表这个String 的实际取值。
这是这种改进,解决了内存泄露的问题。
//构造函数 public String(char value[], int offset, int count) { //check boundary //仅复制需要的部分 this.value = Arrays.copyOfRange(value, offset, offset + count); }
看到这里的评论中,讲:
实际上是String() 和substring() 两个方法在JDK6,JDK7中的区别,是构造方法的实现变了
String sub = old.substring(begin,end);在JDK6中,这个调用会导致 sub.value 与 old.value 引用同一数组内存:
sub.value==old.value为true。而在JDK7中为false。
所以事实上 JDK6的取子串的方法是有效率的 ,而JDK7中的String(char[],int,int)实现中Arrays.copyOfRange的调用 ,虽是本地方法, 但当字符串很大时还是有效率问题。总之JDK7中区别体现更多的是为了安全,而不是性能。
相关文章推荐
- 欢迎使用CSDN-markdown编辑器
- SpringMVC与Struts2中获取request、response对象
- Clean Cache Struts2 Interceptor Tutorial
- ubuntu12.04 安装和配置jdk1.7
- Eclipse配色方案插件
- Struts2 Interceptor Life Cycle
- Spring加载xsd引起的问题小记
- java jxl导出EXCEL
- java判断文件夹是否为空
- java基础入门-iterator迭代器与集合下标的使用
- java基础入门-iterator迭代器与集合下标的使用
- Struts2 Interview Questions and Answers
- jdk:ArrayList
- java jxl 导入EXCEL操作
- jdk Picked up JAVA_TOOL_OPTIONS: -javaagent:/usr/share/java/jayatanaag.jar
- java 判断请求来自手机或电脑
- Java-马士兵设计模式学习笔记-观察者模式-OOD 线程 改进
- Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V
- 在Visual Studio和MyEclipse中建立UML图
- struts2的拦截器AbstractInterceptor