首页 > 编程语言 >String 源码阅读

String 源码阅读

时间:2023-07-10 11:23:29浏览次数:38  
标签:index code String value length 源码 阅读 string

String 源码阅读

1. 属性

/** The value is used for character storage. */
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0

/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
  • 使用 final 修饰的 value。只能初始化一次,如果大量拼接,不可使用该类型
  • 使用字符组进行缓存数据

2. 构造方法

public String()

/**
   * Initializes a newly created {@code String} object so that it represents
   * an empty character sequence.  Note that use of this constructor is
   * unnecessary since Strings are immutable.
   */
  public String() {
      this.value = "".value;
  }
  • 通过设置"".value,实现创建对象.
  • hash 值默认为 0。

public String(String original)

/**
 * Initializes a newly created {@code String} object so that it represents
 * the same sequence of characters as the argument; in other words, the
 * newly created string is a copy of the argument string. Unless an
 * explicit copy of {@code original} is needed, use of this constructor is
 * unnecessary since Strings are immutable.
 *
 * @param  original
 *         A {@code String}
 */
public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}
  • 通过传入的字符串,设置对象,并且设置对应的 hash

public String(char value[])

/**
 * Allocates a new {@code String} so that it represents the sequence of
 * characters currently contained in the character array argument. The
 * contents of the character array are copied; subsequent modification of
 * the character array does not affect the newly created string.
 *
 * @param  value
 *         The initial value of the string
 */
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}
  • 通过传入的字符组进行复制,从而创建对象。

public String(byte bytes[])

    /**
    * Constructs a new {@code String} by decoding the specified array of bytes
    * using the platform's default charset.  The length of the new {@code
    * String} is a function of the charset, and hence may not be equal to the
    * length of the byte array.
    *
    * <p> The behavior of this constructor when the given bytes are not valid
    * in the default charset is unspecified.  The {@link
    * java.nio.charset.CharsetDecoder} class should be used when more control
    * over the decoding process is required.
    *
    * @param  bytes
    *         The bytes to be decoded into characters
    *
    * @since  JDK1.1
    */
   public String(byte bytes[]) {
       this(bytes, 0, bytes.length);
   }
  • 通过字节组进行创建对象,调用该对象的其他方法,传入字节组,开始和结束的位置进行创建

public String(StringBuffer buffer)

/**
 * Allocates a new string that contains the sequence of characters
 * currently contained in the string buffer argument. The contents of the
 * string buffer are copied; subsequent modification of the string buffer
 * does not affect the newly created string.
 *
 * @param  buffer
 *         A {@code StringBuffer}
 */
public String(StringBuffer buffer) {
    synchronized(buffer) {
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}
  • 通过 StringBuffer 进行构建对象,通过 StringBufer.getValue()返回字符组,配合字符组长度创建对象
  • StringBuffer 通过 synchronized 进行出现线程数据共享,由此可见 StringBuffer 是线程安全的

public String(StringBuilder builder)

/**
  * Allocates a new string that contains the sequence of characters
  * currently contained in the string builder argument. The contents of the
  * string builder are copied; subsequent modification of the string builder
  * does not affect the newly created string.
  *
  * <p> This constructor is provided to ease migration to {@code
  * StringBuilder}. Obtaining a string from a string builder via the {@code
  * toString} method is likely to run faster and is generally preferred.
  *
  * @param   builder
  *          A {@code StringBuilder}
  *
  * @since  1.5
  */
 public String(StringBuilder builder) {
     this.value = Arrays.copyOf(builder.getValue(), builder.length());
 }
  • 和上个方法对比,可看出 StringBuilder 线程不安全。

3. 常用方法

字符串的长度 length()

    /**
    * Returns the length of this string.
    * The length is equal to the number of <a href="Character.html#unicode">Unicode
    * code units</a> in the string.
    *
    * @return  the length of the sequence of characters represented by this
    *          object.
    */
   public int length() {
       return value.length;
   }
  • 通过字符组的长度从而获得字符串的长度

是否为空 isEmpty()

    /**
  * Returns {@code true} if, and only if, {@link #length()} is {@code 0}.
  *
  * @return {@code true} if {@link #length()} is {@code 0}, otherwise
  * {@code false}
  *
  * @since 1.6
  */
 public boolean isEmpty() {
     return value.length == 0;
 }
  • 检测是否为空时未检测对象是否为 null,所以使用该方法时需要考虑是否为 null

获得字符串的第几个字符 charAt(int index)

/**
 * Returns the {@code char} value at the
 * specified index. An index ranges from {@code 0} to
 * {@code length() - 1}. The first {@code char} value of the sequence
 * is at index {@code 0}, the next at index {@code 1},
 * and so on, as for array indexing.
 *
 * <p>If the {@code char} value specified by the index is a
 * <a href="Character.html#unicode">surrogate</a>, the surrogate
 * value is returned.
 *
 * @param      index   the index of the {@code char} value.
 * @return     the {@code char} value at the specified index of this string.
 *             The first {@code char} value is at index {@code 0}.
 * @exception  IndexOutOfBoundsException  if the {@code index}
 *             argument is negative or not less than the length of this
 *             string.
 */
public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}
  • 通过传入的字符串的位置进行获取,如果不在返回内会抛出StringIndexOutOfBoundsException异常。

比较内容是否相等 equals(Object object)

/**
 * Compares this string to the specified object.  The result is {@code
 * true} if and only if the argument is not {@code null} and is a {@code
 * String} object that represents the same sequence of characters as this
 * object.
 *
 * @param  anObject
 *         The object to compare this {@code String} against
 *
 * @return  {@code true} if the given object represents a {@code String}
 *          equivalent to this string, {@code false} otherwise
 *
 * @see  #compareTo(String)
 * @see  #equalsIgnoreCase(String)
 */
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
  • 基本的数据类型相等的判断只需要==就可以判断,但是封装类型,需要通过 equals 进行判断。
  • 如果需要对自定义对象进行判断是否相等,需要重写对象的equals方法,从而实现自定义比较方法。如果不重写,则默认比较内存地址。

忽略大小写比较是否相等 equalsIgnoreCase(String anotherString)

/**
 * Compares this {@code String} to another {@code String}, ignoring case
 * considerations.  Two strings are considered equal ignoring case if they
 * are of the same length and corresponding characters in the two strings
 * are equal ignoring case.
 *
 * <p> Two characters {@code c1} and {@code c2} are considered the same
 * ignoring case if at least one of the following is true:
 * <ul>
 *   <li> The two characters are the same (as compared by the
 *        {@code ==} operator)
 *   <li> Applying the method {@link
 *        java.lang.Character#toUpperCase(char)} to each character
 *        produces the same result
 *   <li> Applying the method {@link
 *        java.lang.Character#toLowerCase(char)} to each character
 *        produces the same result
 * </ul>
 *
 * @param  anotherString
 *         The {@code String} to compare this {@code String} against
 *
 * @return  {@code true} if the argument is not {@code null} and it
 *          represents an equivalent {@code String} ignoring case; {@code
 *          false} otherwise
 *
 * @see  #equals(Object)
 */
public boolean equalsIgnoreCase(String anotherString) {
    return (this == anotherString) ? true
            : (anotherString != null)
            && (anotherString.value.length == value.length)
            && regionMatches(true, 0, anotherString, 0, value.length);
}
  1. 进行判断对象的内存地址是否相同--->地址相同,说明同一个对象,自己比较自己肯定 true
  2. 然后判断是否为空,长度是否相同,然后再循环比较每个字符忽略大小写比较

比较字符串的大小 compareTo(String anotherString)


    /**
     * Compares two strings lexicographically.
     * The comparison is based on the Unicode value of each character in
     * the strings. The character sequence represented by this
     * {@code String} object is compared lexicographically to the
     * character sequence represented by the argument string. The result is
     * a negative integer if this {@code String} object
     * lexicographically precedes the argument string. The result is a
     * positive integer if this {@code String} object lexicographically
     * follows the argument string. The result is zero if the strings
     * are equal; {@code compareTo} returns {@code 0} exactly when
     * the {@link #equals(Object)} method would return {@code true}.
     * <p>
     * This is the definition of lexicographic ordering. If two strings are
     * different, then either they have different characters at some index
     * that is a valid index for both strings, or their lengths are different,
     * or both. If they have different characters at one or more index
     * positions, let <i>k</i> be the smallest such index; then the string
     * whose character at position <i>k</i> has the smaller value, as
     * determined by using the &lt; operator, lexicographically precedes the
     * other string. In this case, {@code compareTo} returns the
     * difference of the two character values at position {@code k} in
     * the two string -- that is, the value:
     * <blockquote><pre>
     * this.charAt(k)-anotherString.charAt(k)
     * </pre></blockquote>
     * If there is no index position at which they differ, then the shorter
     * string lexicographically precedes the longer string. In this case,
     * {@code compareTo} returns the difference of the lengths of the
     * strings -- that is, the value:
     * <blockquote><pre>
     * this.length()-anotherString.length()
     * </pre></blockquote>
     *
     * @param   anotherString   the {@code String} to be compared.
     * @return  the value {@code 0} if the argument string is equal to
     *          this string; a value less than {@code 0} if this string
     *          is lexicographically less than the string argument; and a
     *          value greater than {@code 0} if this string is
     *          lexicographically greater than the string argument.
     */
    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }
  1. 找出长度最短的字符串长度
  2. 循环比较,如果有不相等的则返回插值
  3. 一直想等则返回长度差值

判断字符串是否从某个字符串开始的 startsWith(String prefix, int toffset)

/**
    * Tests if the substring of this string beginning at the
    * specified index starts with the specified prefix.
    *
    * @param   prefix    the prefix.
    * @param   toffset   where to begin looking in this string.
    * @return  {@code true} if the character sequence represented by the
    *          argument is a prefix of the substring of this object starting
    *          at index {@code toffset}; {@code false} otherwise.
    *          The result is {@code false} if {@code toffset} is
    *          negative or greater than the length of this
    *          {@code String} object; otherwise the result is the same
    *          as the result of the expression
    *          <pre>
    *          this.substring(toffset).startsWith(prefix)
    *          </pre>
    */
   public boolean startsWith(String prefix, int toffset) {
       char ta[] = value;
       int to = toffset;
       char pa[] = prefix.value;
       int po = 0;
       int pc = prefix.value.length;
       // Note: toffset might be near -1>>>1.
       if ((toffset < 0) || (toffset > value.length - pc)) {
           return false;
       }
       while (--pc >= 0) {
           if (ta[to++] != pa[po++]) {
               return false;
           }
       }
       return true;
   }
  1. 获取对象的字符组、开始位置、传入的字符组,计算得出结束位置
  2. 判断开始位置和结束位置是否超出
  3. 循环比较是否相等

4. 常见问题

标签:index,code,String,value,length,源码,阅读,string
From: https://www.cnblogs.com/jiuxialb/p/17540470.html

相关文章

  • LinkedList 源码阅读
    LinkedList源码阅读LinkedList是通过实现链表从而进行存储的,其有私有内部类Node,通过泛型,从而实现储存各种类型对象。privatestaticclassNode<E>{//该节点的数据Eitem;//链表下一级Node<E>next;//上一级Node<E>prev;//构......
  • CF559B - Equivalent Strings
    首先我们考虑第一种做法,我们搜索\(dp_{x,y,l,r}\)判断\(s[x,y]\)和\(t[l,r]\)是否等价,同时记忆化搜索。但是这样是很明显不行的。如果长度是\(2\)的整次幂,我们仅分析最底层长度为\(1\)的区间,我们发现,任何的\([x,x][y,y](x\len/2)\),都会被搜到一遍。这个可以递归处理,......
  • A011 《千变万化》编程 源码
    一、课程介绍本节课用嵌套for循环、input()获取用户输入、int()转换为整数类型,绘制一个由正多边形组成的花朵。二、重难点解析数据类型数据有类型区分,常用的有整数类型和字符串类型。像10、37、-17、0等数字就是整数类型;而'3'、'27'、'一语惊醒梦中人'、'yyjxmzr'等被引号......
  • 【从0开始编写webserver·基础篇#03】TinyWeb源码阅读,还是得看看靠谱的项目
    【前言】之前通过看书、看视频和博客拼凑了一个webserver,然后有一段时间没有继续整这个项目现在在去看之前的代码,真的是相当之简陋,而且代码设计得很混乱,我认为没有必要继续在屎堆上修改了,于是开始阅读别人的较为规范的开源实现目的是尝试理解一个可用级别的webserver需要具备哪......
  • ThreadLocal源码
    使用场景ThreadLocal用来提供线程局部变量。每个线程都会有一份独立的副本,副本之间不存在竞争关系,是线程专属的内存空间。例如:publicclassThreadLocalTest{privatestaticfinalThreadLocal<Integer>threadLocal=newThreadLocal<>();publicstaticvoidma......
  • Qt源码阅读(五)-deleteLater
    QtdeleteLater作用及源码分析个人经验总结,如有错误或遗漏,欢迎各位大佬指正......
  • String、StringBuffer、StringBuilder 的区别?
    一.介绍String、StringBuffer、StringBuilder:  前言: String、StringBuffer、StringBuilder均在java.lang包下;String: 在Java中,String是一个特殊的引用类型,用于表示文本字符串。它提供了许多方法来操作和处理字符串,比如连接、截取、查找、替换等。String类......
  • 所有源码关注公众号获取
    一、所有源码获取方法:1.关注公众号->商业项目->杂货铺->cv视觉源码;2.根据关键字搜索项目二、项目合作、学生毕设:1.专业的团队,985毕业,大厂工作;2.专业的服务,支持答疑;        公众号:                    个人号: ......
  • String内存模型和Java常用方法
    一、String内存模型1、直接赋值创建string对象内存原理:StringTable(串池):字符串常量池,用来存储字符串,只能是在直接赋值中使用才会存在串池当中(JDK7前串池是在方法区里面,StringTable(串池)在JDK7版本开始从方法区中挪到了堆内存,但是运行机制没有发生变化)eg:首先mian方法进栈,创建变......
  • 基于MFC dll实现C++/CLI dll组件全过程详解(附完整源码) 浮云绘图
    ​模块化组件化实现独立的功能模块是软件设计的良好习惯,一般用实现为DLL。普通的DLL对外提供接口是采用导出函数接口,如果接口数量不大,只是50个以内,这种方式很适合;如果对外接口有上百个,导出函数接口就完全破坏了软件模块化分层设计的理念,使用接口非常麻烦,此情形采用C++/CLI导出类......