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 ...
随机推荐
- python 循环和file操作实现用户密码输错三次将用户锁定
一.需求编写登录接口1.输入用户名密码2.认证成功后显示欢迎信息3.输错三次后锁定 二.简单思路登录,三次密码输入错误锁定用户1.用户信息文件:存放用户名和密码2.黑名单文件:将输入三次错误的用户加入 ...
- CTR预估算法
GBRT(Gradient Boost Regression Tree)渐进梯度回归树,XGBoost是GBRT的一个工程实现 LR(Logistics Regression )逻辑回归 Spark ...
- Appium--入门demo
Appium环境搭建已经在在博客中写出 http://www.cnblogs.com/feimaoyuzhubaobao/p/5057832.html 那么本篇博客主要介绍java版本的appiu ...
- ACM | HDU|6227_Rabbit
题意: 有n只兔子分别占据不同的位置,任意一只兔子可以插入任意两只兔子的之间,但要求两只兔子之间要有空位,求这样的移动次数最多能够有多少? 在这里每一只兔子没有区别,可以看做把 ...
- Nginx之(二)Nginx安装
首先从官网上http://nginx.org/下载最新的stable version源码,当前最新版本为nginx-1.10.2.tar.gz. 2.1 configure 解压之后,会发现里面有一个 ...
- RDO Stack: No valid host was found. There are not enough hosts available.
Issue: When you launch an instance in Newton, you may find that the instance cannot be started due t ...
- 关于Java,那些我心存疑惑的事(不断更新中...)
本文主要列出一些Java常用到确又让大家不怎么注意的问题. 将会不断更新,欢迎关注-- 如有觉得不合理之处,欢迎评论交流,没有火花怎么印象深刻? (1)Java到底是值传递?还是引用传递? 揪出这个问 ...
- TCP发送源码学习(2)--tcp_write_xmit
一.tcp_write_xmit()将发送队列上的SBK发送出去,返回值为0表示发送成功.函数执行过程如下:1.检测拥塞窗口的大小.2.检测当前报文是否完全处在发送窗口内.3.检测报文是否使用nagl ...
- Android支付——支付宝支付总结
摘要:分享牛系列.分享牛转载.第三方支付,java第三方支付.android第三方支付. 原文地址:http://blog.csdn.net/zwl5670/article/details/51219 ...
- 微信小程序基础之表单Form的使用
表单Form的应用很广泛,我们可以利用form设计登录注册,也可以设计一种答题问卷的形式,今天主要讲一下form的使用 form表单,将组件内输入的"switch","i ...