JDK6和JDK7中String的substring()方法及其差异
翻译人员: 铁锚
翻译日期: 2013年11月2日
原文链接: The substring() Method in JDK 6 and JDK 7
在JDK6与JDK7这两个版本中,substring(int beginIndex, int endIndex)方法是不同的. 了解两个版本间的区别可以让你更好地使用它们. 为简单起见,本文中以 substring() 表示 substring(int beginIndex, int endIndex).
1. substring()功能简介
String对象的substring(int beginIndex, int endIndex)方法返回此对象的一个子串,从beginIndex 开始,一直到 endIndex-1 结束,共 (endIndex - beginIndex)个字符。
新手提示:
1.1 String 的索引和数组一样,都是从0开始.
1.2 注意,方法名字是substring(),全小写.
1.3 有个重载方法是substring(int beginIndex),从beginIndex索引处开始,取得子字符串.
String x = "abcdef"; int begin=1; int end=3; x = x.substring(begin, end); System.out.println(x);
执行结果(包含索引为 begin,直到 end-1 的字符):
bc
2. 当substring()被调用时,发生了什么?
你应该知道,因为 x 是不可变的,当 指定 x 等于 x.substring(begin, end)时,实际上 x 指向了一个全新的字符串,如下图所示:
图1
然而,这幅图并不是完全正确的,堆内存中所真正发生的事也不是这么简单.那么,在JDK6和JDK7之间 substring()的调用到底有些什么区别呢?
3. JDK 6中的substring()方法
String实际上是一个字符数组.在 JDK6中, String对象主要包含3个属性域:
private final char value[]; private final int offset; private final int count;
他们用于存储实际的字符数组,数组的第一个索引,以及String的字符个数.
当调用 substring() 方法时,创建了一个新的String对象,但是string的value[] 属性域仍然指向堆内存中的原来的那个数组。区别就是 两个对象的 count 和 offset 这两个值不同了。 如下图所示:
要解释这个问题,下面是最关键部分的代码:
// JDK6,包级私有构造,共享 value数组提升速度
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
// ... 检查边界的代码
// 如果范围和自己一模一样,则返回自身,否则用value字符数组构造一个新的对象
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
4. JDK 6中substring()引起的问题
如果有一个"非常"长的字符串,但每次使用substring()时只想要很小的一部分,那么将会引起另一个性能问题: 虽然你只需要很小的一部分,但是持有了整个value[]的引用,从而导致大量内存被占用。
要解决这个问题,在JDK6中可以让其指向一个真正的子字符串,示例代码:
x = x.substring(begin, end) + "";
5. JDK 7中的substring()方法
在JDK 7 中这个问题得到改进, substring()方法真实地在堆内存中创建了另一个字符数组.
// JDK 7, 权限变为 public
public String(char value[], int offset, int count) {
// ... 检查边界..
// value 数组拷贝
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
public String substring(int beginIndex, int endIndex) {
// ... 检查边界..
int subLen = endIndex - beginIndex;
// 如果和自身一样,那就返回自身,否则返回构造的新对象
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
参考:
2. Java 6 vs Java 7 when implementation matters
相关阅读:
1. Top 10 questions about Java String.
2. Java method for spliting a camelcase string
3. Java: Convert File to Char Array
4. Count Number of Statements in a Java Method By Using Eclipse JDT ASTParser
JDK6和JDK7中String的substring()方法及其差异的更多相关文章
- JDK6与JDK7中String类subString()方法的区别
1.subString()方法的作用 subString(int beginIndex, int endIndex)方法的返回的是以beginIndex开始到 endIndex-1结束的某个调用字符串 ...
- 菜鸟译文(三)——JDK6和JDK7中substring()方法的对比
substring(int beginIndex, int endIndex)方法在JDK6和JDK7中是不同的.了解他们的区别可以让我们更好的使用这个方法.方便起见,以下用substring() 代 ...
- [转]JDK6和JDK7中的substring()方法
substring(int beginIndex, int endIndex)在JDK6与JDK7中的实现方式不一样,理解他们的差异有助于更好的使用它们.为了简单起见,下面所说的substring() ...
- JDK6和JDK7中的substring()方法
substring(int beginIndex, int endIndex)在JDK6与JDK7中的实现方式不一样,理解他们的差异有助于更好的使用它们.为了简单起见,下面所说的substring() ...
- JavaScript中String对象的方法介绍
1.字符方法 1.1 charAt() 方法,返回字符串中指定位置的字符. var question = "Do you like JavaScript?"; alert(ques ...
- Java中String类的方法及说明
String : 字符串类型 一. String sc_sub = new String(c,3,2); // String sb_copy = new String(sb) ...
- 【转载】Java中String类的方法及说明
转载自:http://www.cnblogs.com/YSO1983/archive/2009/12/07/1618564.html String : 字符串类型 一. String sc_ ...
- JS中String添加trim()方法
这么牛的JS竟然还要自己封装trim方法. 下面利用prototype和正则表达式的添加方式添加trim(): <script language="javascript"&g ...
- JavaScript中String.prototype.replace() 方法的使用
摘抄于:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/replace ...
随机推荐
- 2018春招实习笔试面试总结(PHP)
博主双非渣本计算机软件大三狗一枚,眼看着春招就要结束了,现将自己所经历的的整个春招做一个个人总结. 首先就是关于投递计划,博主自己整理了一份各大公司的春招信息,包括网申地址,开始时间,结束时间,以及自 ...
- c#默认类的修饰符。
类的默认修饰符是internal 当其修饰符为internal时,其他模块不能访问该类, 所以class类的修饰符一般为public
- Linux下常用的配置
本文主要给出的都是一些常用的Linux配置,系统版本是基于CentOs6.3,供自己复习和新人学习,不当之处还请指正. vmware tools安装 虚拟机--->安装vmware tools ...
- MYSQL 更新时间自动同步与创建时间默认值共存问题
本文作者:苏生米沿 本文地址:http://blog.csdn.net/sushengmiyan/article/details/50326259 在使用SQL的时候,希望在更新数据的时候自动填充更新 ...
- Android反编译(未混淆的apk)
Android反编译(未混淆的apk) 工具 dex2jar 下载地址:我的CSDN 或者 官网 jd-gui 下载地址:我的CSDN 或者 官网 反编译步骤 1. 将APK解压缩,获取classes ...
- 【Unity Shader】自定义材质面板的小技巧
写在前面 之前遇到过一些朋友问怎么在材质面板里定义类似于bool这种变量,控制一些代码的执行.我们当然可以写一个C#文件来自定义材质面板,就像Unity为Standard Shader写材质面板一样( ...
- ANT不完全总结,包含各种命令,ant例子等,转自:http://lavasoft.blog.51cto.com/62575/87306
ANT不完全总结 好久没有用Ant了,最近让MyEclipse.JBuilder2008逼的重回Ant上了.手生了,写了一个脚本后,重新总结下.参考了官方的文档和网上一些资料. 一.ANT的介 ...
- 让sublime总是在新选项卡打开新文件
sublime的一个默认设置让人很不爽,比如现在选项卡里面已经打开了一个文件A,当你从左边side bar里面点击一个新文件B时,如果你不是快速的双击,且A没有处于编辑未保存状态,那么B就会覆盖A的选 ...
- Linux 高性能服务器编程——TCP/IP协议族
1 TCP/IP协议族体系结构 数据链路层: 职责:实现网卡接口的网络驱动程序,一处理数据在物理媒介(如以太网.令牌环等)上的传输. 常用协议:ARP协议(地址解析协议),RARP协议 ...
- Android Multimedia框架总结(五)多媒体基础概念
转载请把头部出处链接和尾部二维码一起转载,本文出自: http://blog.csdn.net/hejjunlin/article/details/52431887 上篇中介绍了MediaPlayer ...