文档章节

JDK6和JDK7中的substring()方法

crossbell
 crossbell
发布于 2014/06/04 01:01
字数 795
阅读 15
收藏 0
点赞 0
评论 0
本文由 ImportNew - 刘志军 翻译自 programcreek。欢迎加入Java小组。转载请参见文章末尾的要求。

substring(int beginIndex, int endIndex)在JDK6与JDK7中的实现方式不一样,理解他们的差异有助于更好的使用它们。为了简单起见,下面所说的substring()指的就是substring(int beginIndex, int endIndex)方法。

1.substring()是做什么的?

substring(int beginIndex ,int endIndex)方法返回一个子字符串,返回的是从原字符串的beginIndex到endIndex-1之间的内容。

tring x = "abcdef";
x = x.substring(1,3);
System.out.println(x);

输出:

1
"bc"

2.当substring()被调用的时候,内部发生什么事?

你或许会认为由于x是不可变的对象,当x被x.substring(1,3)返回的结果赋值后,它将指向一个全新的字符串如下图:

然而,这个图并不完全正确,或者说并没有完全表示出java 堆中真正发生的事情。那么当调用substring()的时候到底发生的了什么事呢?JDK 6与JDK7的substring方法实现有什么不一样呢?

3.JDK6中的substring()

java中字符串是通过字符数组来支持实现的,在JDK6中,String类包含3个域,char[] value、int offset、int count。分别用于存储真实的字符数组、数组的偏移量,以及String所包含的字符的个数。

当substring()方法被调用的时候,它会创建一个新的字符串对象,但是这个字符串的值在java 堆中仍然指向的是同一个数组,这两个字符串的不同在于他们的count和offset的值。

下面是jdk6中的原代码,是简化后只包含用来说明这个问题的关键代码:

//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);
}

4.jdk6中substring()将会导致的问题

如果你有一个非常长的字符串,但是你仅仅只需要这个字符串的一小部分,这就会导致性能问题(译注:可能会造成内存泄露,这个bug很早以前就有提及),因为你需要的只是很小的部分,而这个子字符串却要包含整个字符数组,在jdk6中解决办法就是使用下面的方法,它会指向一个真正的子字符串。

x = x.substring(x, y) + ""

5.JDK7中的substring()

在JDK7中有所改进,substring()方法在堆中真正的创建了一个新的数组,当原字符数组没有被引用后就被GC回收了.因此避免了上述问题.

//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);
}

译注: 在最新的Oralce JDK 6u45中,substring的实现方式已经改进了,不过我查到openjdk的6-b14就是原来的实现方式,有兴趣的可以查查具体是哪个版改进的.

 
原文链接: programcreek 翻译: ImportNew.com - 刘志军
译文链接: http://www.importnew.com/7418.html
[ 转载请保留原文出处、译者和译文链接。]

本文转载自:http://www.importnew.com/7418.html

共有 人打赏支持
crossbell
粉丝 24
博文 172
码字总数 14545
作品 0
海淀
项目经理
substring()方法在JDK6和JDK7的不同 (翻译外文博客)

substring(int beginIndex, int endIndex)方法在JDK6和JDK7是不一样的,了解两个版本实现它的不同能让你更好地运用它们。 1、substring()的作用是什么? substring(int beginIndex, int endI...

耀子
2015/10/19
73
0
注意:字符串substring方法在jkd6,7,8中的差异。

标题中的substring方法指的是字符串的substring(int beginIndex, int endIndex)方法,这个方法在jdk6,7是有差异的。 substring有什么用? substring返回的是字符串索引位置beginIndex开始,e...

架构之路
2017/11/29
0
0
JDK6 和 JDK7 中的substring()方法

本文由 ImportNew - 刘志军 翻译自 programcreek。如需转载本文,请先参见文章末尾处的转载要求。 substring(int beginIndex, int endIndex)在JDK6与JDK7中的实现方式不一样,理解他们的差异...

编走编想
2013/12/07
0
0
String类的substring方法bug

今天再看JDK源码的时候看到了String类的不同版本的实现方式的不同,主要是substring这个方法,JDK6里面的实现方式是: 很明显可以看到,调用String对象的substring方法后指向的对象地址并没有...

砚羲
2014/09/28
0
0
Java中关于String类型的10个问题

如何比较两个字符串?用“==”还是equals “==”是用来检测两个引用是不是指向内存中的同一个对象,而equals()方法则检测的是两个对象的值是否相等。只要你想检测俩字符串是不是相等的,你就...

神秘的寇先森
2017/12/21
0
0
JDK7和JDK6中substring()的不同

String substring(int beginIndex, int endIndex) 返回原字符串的子字符串这方法,只要是稍微了解点java的人都知道,就像知道1+1==2一样简单。不过其中的猫腻很少有人关注,就像基本没人问1...

浪子_仗剑走天涯
2013/11/21
0
9
jdk6和jdk7不兼容汇总

1、对classes文件的校验,jdk7中method的增加了堆栈映射表属性用于校验。因此任何工具修改字节码文件时都要必须修改更新 堆栈映射表。 2、改进的异常处理导致不兼容。例如以下是jdk6的代码在...

黑牛2008
2013/03/21
6.2K
7
dos下Java命令环境变量失效

背景: 在jdk6和jdk7之前进行切换安装,导致,最后修改环境变量也不能实现jdk版本的切换。 例如,环境变量中,我们配置jdk6环境,但是dos中输入java命令,显示的却仍然是jdk7. 解决方案: 配...

hiqj
2015/10/21
13
0
String常量池和String#intern()

String是Java基础的重要考点。可问的点多,而且很多点可以横向切到其他考点,或纵向深入JVM。 本文略过了String的基本内容,重点在于String#intern()。 String常量池 String常量可能会在两种...

猴子007
2017/12/25
0
0
JDK7-Collections.sort()报Comparison method violates its general contract异常

记录在 JDK7 下使用 Collections.sort() 排序偶发的一个异常,以前在 JDK1.6 下面没有这个问题: Comparison method violates its general contract 发生问题的代码段: 一个很简单的排序,在...

山哥
2016/09/12
119
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

线程安全,底层实现原理和JMM

让多线程下的类安全起来:无状态、加锁、让类不可变、栈封闭(方法封装) 、安全的发布对象(不暴露成员) 死锁 一定发生在多个线程争夺多个资源里的情况下,发生的原因是每个线程拿到了某个(某...

这很耳东先生
7分钟前
0
0
MyBatis源码解读之延迟加载

1. 目的 本文主要解读MyBatis 延迟加载实现原理 2. 延迟加载如何使用 Setting 参数配置 设置参数 描述 有效值 默认值 lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延...

无忌
13分钟前
0
0
javascript 类变量的实现

代码如下: function echo(){ for(let i=0;i<arguments.length;i++) console.log(arguments[i]);}function extend(o, p){for (prop in p) {o[prop] = p[prop]}retur......

backbye
17分钟前
0
2
编程语言对比分析:Python与Java和JavaScript(图)

编程语言对比分析:Python与Java和JavaScript(图): 凭什么说“Python 太慢,Java 太笨拙,我讨厌 JavaScript”?[图] 编程语言生而为何? 我们人类从原始社会就是用语言表达自己,互相沟通...

原创小博客
25分钟前
0
0
Akka构建Reactive应用《one》

看到这Akka的官网,描述使用java或者scala构建响应式,并发和分布式应用更加简单,听着很高级的样子,下面的小字写着消息驱动,但是在quickstart里面又写容错事件驱动,就是这么钻牛角尖。 ...

woshixin
37分钟前
0
0
ffmpeg源码分析 (四)

io_open 承接上一篇,对于avformat_open_input的分析还差其中非常重要的一步,就是io_open,该函数用于打开FFmpeg的输入输出文件。 在init_input中有这么一句 if ((ret = s->io_open(s, &s-...

街角的小丑
39分钟前
0
0
String,StringBuffer ,StringBuilder的区别

不同点 一、基类不同 StringBuffer、StringBuilder 都继承自AbStractStringBuilder,String 直接继承自 Object 2、底层容器“不同” 虽然底层都是字符数组,但是String的是final修饰的不可变...

不开心的时候不要学习
54分钟前
0
0
nodejs 文件操作

写文件code // 加载文件模块var fs = require("fs");var content = 'Hello World, 你好世界!';//params 文件名,内容,编码,回调fs.writeFile('./hello.txt',content,'utf8',function (er......

yanhl
56分钟前
0
0
SpringBoot mybits 查询为0条数据 但是在Navicat 中可以查询到数据

1.页面请求: 数据库查询: 2018-07-16 17:56:25.054 DEBUG 17312 --- [nio-9010-exec-3] c.s.h.m.C.selectSelective : ==> Preparing: select id, card_number, customer_id, customer_nam......

kuchawyz
今天
0
0
译:Self-Modifying cod 和cacheflush

date: 2014-11-26 09:53 翻译自: http://community.arm.com/groups/processors/blog/2010/02/17/caches-and-self-modifying-code Cache处在CPU核心与内存存储器之间,它给我们的感觉是,它具......

我叫半桶水
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部