Java substring方法实现原理解析

 更新时间:2020年05月01日 10:36:41   作者:Hello_xzy_World  
这篇文章主要介绍了Java substring方法实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

substring实现原理

String是Java中一个比较基础的类,每一个开发人员都会经常接触到。而且,String也是面试中经常会考的知识点。String有很多方法,有些方法比较常用,有些方法不太常用。今天要介绍的subString就是一个比较常用的方法,而且围绕subString也有很多面试题。

substring(int beginIndex, int endIndex)方法在不同版本的JDK中的实现是不同的。了解他们的区别可以帮助你更好的使用他。为简单起见,后文中用substring()代表substring(int beginIndex, int endIndex)方法。

substring()的作用

substring(int beginIndex, int endIndex)方法截取字符串并返回其[beginIndex,endIndex-1]范围内的内容。s

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

输出内容:

bc

调用substring时发生了什么?

你可能知道,因为x是不可变的,当使用x.substring(1,3)对x赋值的时候,它会指向一个全新的字符串:

然而,这个图不是完全正确的表示堆中发生的事情。因为在jdk6 和 jdk7中调用substring时发生的事情并不一样。

JDK 6中的subString

tring是通过字符数组实现的。在jdk 6 中,String类包含三个成员变量:char value[], int offset,int count,他们分别用来:存储真正的字符数组、存储数组的第一个位置索引、存储字符串中包含的字符个数。

当调用substring方法的时候,会创建一个新的string对象,但是这个string的值仍然指向堆中的同一个字符数组。这两个对象中只有count和offset 的值是不同的。

源码

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

存在的问题

如果有一个很长的字符串,但是你只需要使用很短的一段,于是你使用substring进行切割,但是由于你实际上引用了整个字符串,这个很长的字符串无法被回收。往小了说,造成了存储空间的浪费,往大了说,可能造成内存泄漏。这个问题已经被官方记录在Java Bug Database里面了:

相应的解决办法:

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

JDK 7 中的substring

上述问题在JDK 7中得到了解决。JDK 7中,substring方法会在堆中创建一个新的数组。

源码

  //JDK 7

  /**
   * Allocates a new {@code String} that contains characters from a subarray
   * of the character array argument. The {@code offset} argument is the
   * index of the first character of the subarray and the {@code count}
   * argument specifies the length of the subarray. The contents of the
   * subarray are copied; subsequent modification of the character array does
   * not affect the newly created string.
   *
   * @param value Array that is the source of characters
   * @param offset The initial offset
   * @param count The length
   * @throws IndexOutOfBoundsException If the {@code offset} and {@code count} arguments index
   *                  characters outside the bounds of the {@code value} array
   */
  public String(char value[], int offset, int count) {
    //check boundary
    this.value = Arrays.copyOfRange(value, offset, offset + count);
  }

  /**
   * Returns a string that is a substring of this string. The
   * substring begins at the specified {@code beginIndex} and
   * extends to the character at index {@code endIndex - 1}.
   * Thus the length of the substring is {@code endIndex-beginIndex}.
   * <p>
   * Examples:
   * <blockquote><pre>
   * "hamburger".substring(4, 8) returns "urge"
   * "smiles".substring(1, 5) returns "mile"
   * </pre></blockquote>
   *
   * @param beginIndex the beginning index, inclusive.
   * @param endIndex  the ending index, exclusive.
   * @return the specified substring.
   * @throws IndexOutOfBoundsException if the
   *                  {@code beginIndex} is negative, or
   *                  {@code endIndex} is larger than the length of
   *                  this {@code String} object, or
   *                  {@code beginIndex} is larger than
   *                  {@code endIndex}.
   */
  public String substring(int beginIndex, int endIndex) {
    //check boundary
    int subLen = endIndex - beginIndex;
    return ((beginIndex == 0) && (endIndex == value.length)) ?
        this :
        new String(value, beginIndex, subLen);
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 详解大数据处理引擎Flink内存管理

    详解大数据处理引擎Flink内存管理

    Flink是jvm之上的大数据处理引擎,jvm存在java对象存储密度低、full gc时消耗性能,gc存在stw的问题,同时omm时会影响稳定性。针对频繁序列化和反序列化问题flink使用堆内堆外内存可以直接在一些场景下操作二进制数据,减少序列化反序列化消耗。本文带你详细理解其原理。
    2021-05-05
  • springboot集成shiro详细总结

    springboot集成shiro详细总结

    这几天在看 shiro,用 springboot 集成了一下,下面的这个例子中主要介绍了 shiro 的认证和授权,以及盐值加密的功能.程序可以运行起来.这里只做一个简单的介绍,后续会针对各个功能做一个详细的介绍,这里不做过多的赘述,需要的朋友可以参考下
    2021-05-05
  • java GUI实现ATM机系统(3.0版)

    java GUI实现ATM机系统(3.0版)

    这篇文章主要为大家详细介绍了java GUI实现ATM机系统(3.0版),文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • java读取excel图片导入代码示例(亲测有效)

    java读取excel图片导入代码示例(亲测有效)

    在日常工作中,我们经常要将一些照片插入到Excel表格中,这篇文章主要给大家介绍了关于java读取excel图片导入的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • Mybatis应用mysql存储过程查询数据实例

    Mybatis应用mysql存储过程查询数据实例

    下面小编就为大家分享一篇Mybatis应用mysql存储过程查询数据实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • 详解SpringMVC学习系列(6) 之 数据验证

    详解SpringMVC学习系列(6) 之 数据验证

    这篇文章主要介绍了详解SpringMVC学习系列(6) 之 数据验证 ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-12-12
  • SSM框架整合之junit测试的方法

    SSM框架整合之junit测试的方法

    本篇文章主要介绍了SSM框架整合之junit测试的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • springboot框架阿里开源低代码工具LowCodeEngine

    springboot框架阿里开源低代码工具LowCodeEngine

    这篇文章主要为大家介绍了springboot框架阿里开源低代码LowCodeEngine工具使用详解有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 在Java Spring框架中使用的设计模式有哪些

    在Java Spring框架中使用的设计模式有哪些

    面试中常会被问道Spring框架使用了哪些设计模式?关于这个问题本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • JDK-StringJoiner构造及添加元素源码分析

    JDK-StringJoiner构造及添加元素源码分析

    这篇文章主要为大家介绍了JDK-StringJoiner构造及添加元素源码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07

最新评论