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);
}
参考:
1. Changes to substring
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中的substring()方法
2019独角兽企业重金招聘Python工程师标准>>> substring(int beginIndex, int endIndex)在JDK6与JDK7中的实现方式不一样,理解他们 ...
- c++中string的assign方法使用
c++中string的assign方法使用 string的实际.h和.cpp文件是basic_string.h 和basic_string.tcc,所以string中assign也在这两个文件声明和定 ...
- JAVA中String的split方法
我的个人网站: http://riun.xyz 以下源码版本:JDK1.8 简介 Java 中 String 的 split 方法可以将字符串根据指定的间隔进行切割,例如字符串 str = " ...
- Java中String类的方法及说明
String : 字符串类型 一.构造函数 String(byte[ ] bytes):通过byte数组构造字符串对象. String(char[ ] value):通过char数 ...
- 【转载】Java中String类的方法及说明
转载自:http://www.cnblogs.com/YSO1983/archive/2009/12/07/1618564.html String : 字符串类型 一.构造函数 String ...
- String类substring方法
踩了一个坑,记录一下String类的substring方法. substring方法可以用来截取字符串,它有两种表现形式: substring(int beginIndex) substring(in ...
- javascript中String的fromCharCode()方法
前几天遇到一个bug,后端的模板引擎在输出形如: <div title="111 aaa">内容</div> 这样的内容时,无法输出' '空格,所以只能用' ...
- JDK8中String的intern()方法详细解读【内存图解+多种例子+1.1w字长文】
文章目录 一.前言 二.图文理解String创建对象 1.例子一 2.例子二 3.例子三 4.例子四 5.例子五 6.例子六 三.深入理解intern()方法 1. 源码查看 2. 例子一 3. 例子 ...
- Java中String类 compareTo()方法比较字符串详解
中心:String 是字符串,它的比较用compareTo方法,它从第一位开始比较, 如果遇到不同的字符,则马上返回这两个字符的ascii值差值.返回值是int类型 1.当两个比较的字符串是英文且长度 ...
- C库中没有itoa以及C++中string没有split方法的原因
个人见解,欢迎讨论.这其实源于c/c++需要自己管理内存,而一个好的惯例是 自己申请的内存要自己释放掉 所以c/c++库函数一般都不会返回指针,你会说有些函数返回指针了呀,如 char *strcpy ...
最新文章
- request.getparameter特殊字符变成?号问号_15 个不可不知的 Linux 特殊字符,你懂几个?...
- 前端学习(2950):webpack目录结构
- Vasya and Multisets CodeForces - 1051C 模拟|分类讨论
- Qt工作笔记-使用QpropertyAnimation实现控件上下滑动的效果
- Android 驱动(15)---如何修改USB驱动能力
- java栈最小值的实现,关于java:算法图解如何找出栈中的最小值
- java海滩上有一_海滩上有一堆桃子,五只猴子来分-海滩上有一堆桃子,五只猴子来分java实现-吾爱编程网...
- linux中fork() 函数详解
- 牛客网项目——项目开发(十):热帖排行,生成长图,上传云服务器,性能优化
- unexpected error while obtaining UI hierarchy
- 将你的 Python 脚本转换为命令行程序
- 【无标题】【思特奇杯·云上蓝桥-算法集训营】第1周
- java 计算星座算法,java 依据生日计算星座
- 在MATLAB中创建函数
- sqlite expert 教程
- Drupal9自定义module添加多个定时任务
- 用python通过selenium自动化测试抓取天猫店铺数据
- [HDU1004] Let the balloon rise - 让气球升起来
- 性能测试工具Locust和JMeter比较
- 【智能CAN/串口转换器提供“透明转换、透明带标识转换和自定义协议转换”三种转换模式介绍、CAN转换器、CAN 485、CAN 232】
热门文章
- 在Ubuntu安装QT及相关环境配置
- 刷网课-踩坑——jsDOM获取不到页面元素节点-iframe标签获取元素节点
- 查纸张开数软件怎么样
- 客户管理系统代码项目_低代码案例:快速交付包含门店销售终端的SCM供应链管理系统...
- 通讯录系统课程设计——链表实现——c语言
- 树莓派4B改装RC玩具车玩转opencv系列教程(一)树莓派基础入门篇------Hello Raspberry Pi OS(Rasbian )!
- 物联网工程导论第二版答案选择题
- 队列(纯C语言实现)
- 华硕重装系统键盘灯失效 =重装ATK驱动
- 如何将html转换成url,HTML URL