java7里有jdk吗_简易Java(07):substring()方法在JDK6和JDK7中的异同 | "地瓜哥"博客网...

看到substring(),D瓜哥就想起来去年面试的惨痛精力。连续两次被问到substring()会造成什么问题;第一次被问到时,确实不知道会造成什么问题,面试结束后就查了查资料。但是,没有认真看。没想到接下来的面试又问到,由于没有看,还是没回答上来,结果面试就惨遭失败!

没想到,这次又遇到了substring()。所以,这篇文章D瓜哥必须好好翻译!

substring()会造成什么问题,请看参考资料。

另外,需要提前说明一点,本节内容是针对Oracle JDK来说明的,其他JDK的实现也许可能不同。请读者自己查看相关文档以及源代码。

substring(int beginIndex, int endIndex)方法,在JDK6和JDK7中的实现是不一样的。了解实现的不同之处,可以帮助我们更好地使用这个方法。为了简单起见,下文中用substring()指代substring(int beginIndex, int endIndex)。

1、substring()的作用是啥?

substring(int beginIndex, int endIndex)方法将返还字符串,这个字符串是原字符串从beginIndex开始,到endIndex-1的子串。

1/**

3*/

4

5String x ="abcd";

6x = x.substring(1,3);

7System.out.println(x);

输出为:

1

2、当substring()被调用时,背后发生了什么?

我们在上一篇文章“图解Java字符串的不可变性 ”讲到,字符串x是不可变的。所以,当x被重新赋值为x.substring(1, 3)时,它指向了一个全新的字符串。如下图所示:

41828048_1.png

尽管,这个图并不能完全正确地说明堆栈中的确实发生的变化。不过,却可以帮助我们说明,当substring()被调用时,在JDK6和JDK7下究竟有什么不同。

3、JDK6中的substring()

字符串是通过字符数组的方式来实现的。在JDK6中,String类包含三个属性:char value[]、int offset、int count,它们分别用于存储真实的字符数组、数组的开始下标以及字符串中的字符数量。

当调用substring()时,它将创建一个新的字符串对象,但是字符串的值还是指向堆栈中同一个数组。两个字符串对象不同的只是它们的字符数量以及开始下标。如下图所示:

41828048_2.png

01/**

03*/

04

05// JDK 6

06String(int offset,int count,char value[]) {

07this.value = value;

08this.offset = offset;

09this.count = count;

10}

11

12public String substring(int beginIndex,int endIndex) {

13// 边界检查

14return new String(offset + beginIndex, endIndex - beginIndex, value);

15}

4、JDK6的substring()导致的问题

如果你有一个非常长的字符串,但是你每次调用substring(),只需要其中的很小一部分。那么,这将导致一个性能问题,尽管你仅仅需要很小的一部分,但是,却保存了所有的字符。对于JDK6,使用下面的代码,可以解决这个问题,可以使得对象x确实指向一个真正的子字符串:

1x = x.substring(m, n) +"";

5、JDK7中的substring()

上面提到的问题,在JDK7中已经改正。在JDK7中,substring()方法确实会在堆栈中创建一个新的数组。如下图所示:

41828048_3.png

D瓜哥注:

这个图片有部分地方是错误的:int count和int offset已经不是Oracle JDK7中String的属性。大家可以从String的源代码中确认!

01/**

03*/

04

05// JDK 7

06String(char value[],int offset,int count) {

07// 边界检查

08this.value = Arrays.copyOfRange(value, offset, offset+count);

09}

10

11public String substring(int beginIndex,int endIndex) {

12// 边界检查

13int subLen = endIndex - beginIndex;

14return ((beginIndex ==0) && (endIndex == value.length)) ?this

15:new String(value, beginIndex, subLen);

16}

《Simple Java》是一本讲解Java面试题的书。讲解也有不少独特之处,为了面试,《简易Java》走起!

参考资料

如果感觉这篇文章不错,请点击这里的分享按钮,分享到微博等地方去,让更多人受益!

您的支持是D瓜哥最大的写作动力!谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值