【Java基础】字符串String

目录

前言

构造方法

1.String()

2.String(String original)

3.String(char value[])

4.String(char value[], int offset, int count)

5.String(int[] codePoints, int offset, int count)

6.String(byte bytes[], int offset, int length, String charsetName)

7.String(byte bytes[], int offset, int length, Charset charset)

8.String(byte bytes[], String charsetName)

9.String(byte bytes[], Charset charset)

10.String(byte bytes[], int offset, int length)

11.String(byte bytes[])

12.String(StringBuffer buffer)

13.String(StringBuilder builder)

常用方法

1.int length()

2.boolean isEmpty()

3.char charAt(int index)

4.int codePointAt(int index)

5.int codePointBefore(int index)

6.int codePointCount(int beginIndex, int endIndex)

7.int offsetByCodePoints(int index, int codePointOffset)

8.void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)

 9.byte[] getBytes(String charsetName)

10.byte[] getBytes(Charset charset)

11.byte[] getBytes() 

12.boolean equals(Object anObject)

13.boolean contentEquals(StringBuffer sb)

14.boolean contentEquals(CharSequence cs)

15.boolean equalsIgnoreCase(String anotherString)

16.int compareTo(String anotherString)

17.int compareToIgnoreCase(String str)

18.boolean regionMatches(int toffset, String other, int ooffset, int len)

19.boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)

20.boolean startsWith(String prefix, int toffset)

21.boolean startsWith(String prefix)

22.boolean endsWith(String suffix)

23.int hashCode()

24.int indexOf(int ch)

25.int indexOf(int ch, int fromIndex)

26.int lastIndexOf(int ch)

27.int lastIndexOf(int ch, int fromIndex)

28. int indexOf(String str)

29.int indexOf(String str, int fromIndex)

30.int lastIndexOf(String str) 

31.int lastIndexOf(String str, int fromIndex)

32.String substring(int beginIndex)

33.String substring(int beginIndex, int endIndex)

34.CharSequence subSequence(int beginIndex, int endIndex)

35.String concat(String str)

36.String replace(char oldChar, char newChar)

37.boolean matches(String regex)

38.boolean contains(CharSequence s)

39.String replaceFirst(String regex, String replacement)

40.String replaceAll(String regex, String replacement)

41.String replace(CharSequence target, CharSequence replacement)

42.String[] split(String regex, int limit)

 43.String[] split(String regex)

44.String join(CharSequence delimiter, CharSequence... elements)

45.String join(CharSequence delimiter, Iterable elements)

46.String toLowerCase(Locale locale)

47.String toLowerCase()

48.String toUpperCase(Locale locale)

49.String toUpperCase()

50.String trim()

51.String toString()

52.char[] toCharArray()

53.String format(String format, Object... args)

54.String format(Locale l, String format, Object... args)

55.String valueOf(Object obj)

56.String valueOf(char data[])

57.String valueOf(char data[], int offset, int count)

58.String copyValueOf(char data[], int offset, int count)

59.String copyValueOf(char data[])

60.String valueOf(boolean b)

61.String valueOf(char c)

62.String valueOf(int i)

63.String valueOf(long l)

64.String valueOf(float f)

65.String valueOf(double d)

66.String intern()

常见问题

JDK源码当中有多处 might be near -1>>>1 的注释,这个是什么意思?

为什么 -1>>>1 的值是Integer.MAX_VALUE?


前言

String表示的是字符串类型,不属于基础数据类型。

在Java中可以直接使用双引号表示字符串

String s = "abc";

在JDK1.8中String类的定义如下

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
    /** 用于存储字符串的值 */
    private final char value[];

    /** 字符串的hash值 */
    private int hash; // 默认是0

    ...
}
  1. String类被final修饰,表示String类是一个最终类,即:不允许被继承
  2. String类实现了Serializable、Comparable、CharSequence接口。
  3. String内部维护char数组实现存储字符串的值。

构造方法

1.String()

public String() {
    this.value = "".value;
}

构造一个空的字符串对象。注:因为字符串是不可变对象,所以一般不使用此构造方法。

2.String(String original)

public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}

构造一个与参数相同的字符串对象。新的字符串对象是参数字符串的副本。除非需要使用原始字符串的显式副本,否则不需要使用此构造方法,因为String是不可变对象。

3.String(char value[])

public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}

构造一个新的字符串对象,以便用它来表示char数组的字符序列。复制char数组的内容,char数组参数的后续修改不会影响新创建的字符串。

4.String(char value[], int offset, int count)

public String(char value[], int offset, int count) {
  if (offset < 0) {
    throw new StringIndexOutOfBoundsException(offset);
  }
  if (count <= 0) {
    if (count < 0) {
      throw new StringIndexOutOfBoundsException(count);
    }
    if (offset <= value.length) {
      this.value = "".value;
      return;
    }
  }
  /*
   * 注意: offset或者 count的值可能接近 -1>>>1 的值
   * -1 >>> 1 的值即为Integer.MAX_VALUE
   * 这里的判断是为了防止offset + count > value.length
   * 但是当offset或者count的值接近Integer.MAX_VALUE时,offset + count会溢出,此时offset + count > value.length 为false
   * 所以此处使用 offset > value.length - count 判断
   */
  if (offset > value.length - count) {
    throw new StringIndexOutOfBoundsException(offset + count);
  }
  this.value = Arrays.copyOfRange(value, offset, offset+count);
}

构造一个包含字符数组参数的子数组中的字符的新字符串对象。offset参数是子数组第一个字符的索引,count参数指定子数组的长度。复制数组的内容;字符数组的后续修改不会影响新创建的字符串。

5.String(int[] codePoints, int offset, int count)

public String(int[] codePoints, int offset, int count) {
  if (offset < 0) {
    throw new StringIndexOutOfBoundsException(offset);
  }
  if (count <= 0) {
    if (count < 0) {
      throw new StringIndexOutOfBoundsException(count);
    }
    if (offset <= codePoints.length) {
      this.value = "".value;
      return;
    }
  }
  // 注意: offset或者 count的值可能接近 -1>>>1 的值
  if (offset > codePoints.length - count) {
    throw new StringIndexOutOfBoundsException(offset + count);
  }

  final int end = offset + count;

  // 第一步:计算char数组的精确长度
  int n = count;
  for (int i = offset; i < end; i++) {
    int c = codePoints[i];
    // 如果是Bmp码点
    if (Character.isBmpCodePoint(c))
      continue;
      // 是否为有效码点
    else if (Character.isValidCodePoint(c))
      n++;
    else throw new IllegalArgumentException(Integer.toString(c));
  }

  // 第二步:填充char数组
  final char[] v = new char[n];

  for (int i = offset, j = 0; i < end; i++, j++) {
    int c = codePoints[i];
    // 如果是Bmp码点
    if (Character.isBmpCodePoint(c))
      v[j] = (char)c;
    else
      Character.toSurrogates(c, v, j++);
  }

  this.value = v;
}

构造一个包含Unicode码点数组参数的子数组中的字符的新字符串对象。offset参数是子数组第一个码点的索引,count参数指定子数组的长度。子数组的内容被转换为字符;int数组的后续修改不会影响新创建的字符串。

6.String(byte bytes[], int offset, int length, String charsetName)

public String(byte bytes[], int offset, int length, String charsetName)
    throws UnsupportedEncodingException {
  if (charsetName == null)
    throw new NullPointerException("charsetName");
  checkBounds(bytes, offset, length);
  this.value = StringCoding.decode(charsetName, bytes, offset, length);
}

通过使用指定的字符集解码指定的字节子数组来构造一个新的字符串。新字符串的长度是由指定的字符集决定的,因此可能不等于子数组的长度。

7.String(byte bytes[], int offset, int length, Charset charset)

public String(byte bytes[], int offset, int length, Charset charset) {
  if (charset == null)
    throw new NullPointerException("charset");
  checkBounds(bytes, offset, length);
  this.value =  StringCoding.decode(charset, bytes, offset, length);
}

通过使用指定的字符集解码指定的字节子数组来构造一个新的字符串。新字符串的长度是由指定的字符集决定的,因此可能不等于子数组的长度。

8.String(byte bytes[], String charsetName)

public String(byte bytes[], String charsetName)
    throws UnsupportedEncodingException {
  this(bytes, 0, bytes.length, charsetName);
}

通过使用指定的字符集解码指定的字节数组来构造新的字符串。新字符串的长度是由指定的字符集决定的,因此可能不等于字节数组的长度。 

9.String(byte bytes[], Charset charset)

public String(byte bytes[], Charset charset) {
  this(bytes, 0, bytes.length, charset);
}

通过使用指定的字符集解码指定的字节数组来构造新的字符串。新字符串的长度是由指定的字符集决定的,因此可能不等于字节数组的长度。 

10.String(byte bytes[], int offset, int length)

public String(byte bytes[], int offset, int length) {
  checkBounds(bytes, offset, length);
  this.value = StringCoding.decode(bytes, offset, length);
}

通过使用平台的默认字符集解码指定的字节子数组来构造一个新字符串。新字符串的长度是由平台字符集决定的,因此可能不等于子数组的长度。

11.String(byte bytes[])

public String(byte bytes[]) {
  this(bytes, 0, bytes.length);
}

通过使用平台字符集解码指定的字节数组来构造新的字符串。新字符串的长度是由平台字符集决定的,因此可能不等于字节数组的长度。 

12.String(StringBuffer buffer)

public String(StringBuffer buffer) {
  synchronized(buffer) {
    this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
  }
}

分配包含StringBuffer参数中当前包含的字符序列的新字符串。复制StringBuffer的内容;StringBuffer的后续修改不会影响新创建的字符串。

13.String(StringBuilder builder)

public String(StringBuilder builder) {
  this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

分配包含StringBuilder参数中当前包含的字符序列的新字符串。复制StringBuilder的内容;StringBuilder的后续修改不会影响新创建的字符串。


常用方法

1.int length()

public int length() {
  return value.length;
}

返回此字符串的长度。长度等于字符串中Unicode编码单元的数量。

// 返回字符串的Unicode编码单元的数量
String s = "abcdefg";
System.out.println(s.length()); // 7

// 例如emoji表情为双Unicode编码单元
String s = "abcdefg😠";
System.out.println(s.length()); // 9

2.boolean isEmpty()

public boolean isEmpty() {
  return value.length == 0;
}

当且仅当 value.length为0时,返回true,否则返回false。

System.out.println("abcdefg".isEmpty()); // false
System.out.println("".isEmpty()); // true
System.out.println(" ".isEmpty()); // false

3.char charAt(int index)

public char charAt(int index) {
  if ((index < 0) || (index >= value.length)) {
    throw new StringIndexOutOfBoundsException(index);
  }
  return value[index];
}

返回指定索引处的字符值。索引的范围从0到length()-1。序列的第一个字符值位于索引0,下一个字符值在索引1,依此类推。

String s = "abcdefg😠";
// 😠 为 "\uD83D\uDE20"
System.out.println(s.charAt(0)); // a
System.out.println(s.charAt(7)); // ?
System.out.println(s.charAt(7) == '\uD83D'); // true
System.out.println(s.charAt(8) == '\uDE20'); // true

4.int codePointAt(int index)

public int codePointAt(int index) {
  if ((index < 0) || (index >= value.length)) {
    throw new StringIndexOutOfBoundsException(index);
  }
  return Character.codePointAtImpl(value, index, value.length);
}

返回指定索引处的字符(Unicode码点)。索引引用字符值(Unicode代码单位),范围从0到length() - 1。

String s = "abcdefg😠";
// 😠 为 "\uD83D\uDE20"
System.out.println(s.codePointAt(0)); // 97
System.out.println(s.codePointAt(7)); // 1258544
System.out.println(s.codePointAt(8)); // 56864 56864即为\uDE20
System.out.println(s.codePointAt(7) == '\uD83D'); // false
System.out.println(s.codePointAt(8) == '\uDE20'); // true

5.int codePointBefore(int index)

public int codePointBefore(int index) {
  int i = index - 1;
  if ((i < 0) || (i >= value.length)) {
    throw new StringIndexOutOfBoundsException(index);
  }
  return Character.codePointBeforeImpl(value, index, 0);
}

返回指定索引之前的字符(Unicode码点)。索引引用字符值(Unicode单位),范围从1到length。

String s = "abcdefg😠";
// 😠 为 "\uD83D\uDE20"
System.out.println(s.codePointBefore(1)); // 97
System.out.println(s.codePointBefore(8)); // 55357 55357即为\uD83D
System.out.println(s.codePointBefore(9)); // 128544
System.out.println(s.codePointBefore(8) == '\uD83D'); // true
System.out.println(s.codePointBefore(9) == '\uDE20'); // false

6.int codePointCount(int beginIndex, int endIndex)

public int codePointCount(int beginIndex, int endIndex) {
  if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
    throw new IndexOutOfBoundsException();
  }
  return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
}

返回此字符串的指定文本范围内的Unicode码点数。文本范围从指定的beginIndex开始,到索引endIndex-1处的字符为止。因此,文本范围的长度(以字符为单位)为endIndex - beginIndex。

// 😠 为 "\uD83D\uDE20"
System.out.println("abcdefg😠".codePointCount(0, "abcdefg😠".length())); // 8
System.out.println("abcdefg".codePointCount(0, "abcdefg".length())); // 7

7.int offsetByCodePoints(int index, int codePointOffset)

public int offsetByCodePoints(int index, int codePointOffset) {
  if (index < 0 || index > value.length) {
    throw new IndexOutOfBoundsException();
  }
  return Character.offsetByCodePointsImpl(value, 0, value.length,
      index, codePointOffset);
}

返回此字符串中与给定索引偏移codePointOffset码点的索引。在索引和codePointOffset给定的文本范围内,未配对的替代项各计为一个码点。 

// 😠 为 "\uD83D\uDE20"
String s = "abcdefg😠";
System.out.println(s.offsetByCodePoints(0, 7)); // 7
System.out.println(s.offsetByCodePoints(0, 8)); // 9

8.void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
  if (srcBegin < 0) {
    throw new StringIndexOutOfBoundsException(srcBegin);
  }
  if (srcEnd > value.length) {
    throw new StringIndexOutOfBoundsException(srcEnd);
  }
  if (srcBegin > srcEnd) {
    throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
  }
  System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

将此字符串中的字符复制到目标字符数组中。

要复制的第一个字符位于索引srcBegin;要复制的最后一个字符位于索引srcEnd - 1(因此要复制的字符总数为srcEnd - srcBegin。字符被复制到dst的子数组中,从索引dstBegin开始,到索引结尾:dstBegin + (srcEnd - srcBegin) - 1。

// 😠 为 "\uD83D\uDE20"
String s = "abcdefg😠";
char[] chars = new char[s.length()];
s.getChars(0, 1, chars, 0);
System.out.println(chars);  // [a, , , , , , , , ]
// 😠 为 "\uD83D\uDE20"
String s = "abcdefg😠";
char[] chars = new char[s.length()];
s.getChars(0, 1, chars, 0);
System.out.println(chars);  // [a, , , , , , , , ]
s.getChars(7, 8, chars, 0);
System.out.println(chars);  // ['\uD83D', , , , , , , , ]
s.getChars(7, 9, chars, 0);
System.out.println(chars);  // ['\uD83D', '\uDE20', , , , , , , ]

 9.byte[] getBytes(String charsetName)

public byte[] getBytes(String charsetName)
    throws UnsupportedEncodingException {
  if (charsetName == null) throw new NullPointerException();
  return StringCoding.encode(charsetName, value, 0, value.length);
}

使用指定的字符集将此字符串编码为字节序列,并将结果存储到新的字节数组中。

String s = "abcdefg😠";
byte[] bytes = s.getBytes("UTF-8");
System.out.println(bytes); // [97, 98, 99, 100, 101, 102, 103, -16, -97, -104, -96]
bytes = s.getBytes("ISO-8859-1");
System.out.println(bytes); // [97, 98, 99, 100, 101, 102, 103, 63]

10.byte[] getBytes(Charset charset)

public byte[] getBytes(Charset charset) {
  if (charset == null) throw new NullPointerException();
  return StringCoding.encode(charset, value, 0, value.length);
}

使用指定的字符集将此字符串编码为字节序列,并将结果存储到新的字节数组中。此方法始终使用此字符集的默认替换字节数组替换格式错误的输入和不可映射的字符序列。

String s = "abcdefg😠";
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
System.out.println(bytes); // [97, 98, 99, 100, 101, 102, 103, -16, -97, -104, -96]
bytes = s.getBytes(StandardCharsets.ISO_8859_1);
System.out.println(bytes); // [97, 98, 99, 100, 101, 102, 103, 63]

11.byte[] getBytes() 

public byte[] getBytes() {
  return StringCoding.encode(value, 0, value.length);
}

使用平台的默认字符集将此字符串编码为字节序列,并将结果存储到新的字节数组中。 

String s = "abcdefg😠";
byte[] bytes = s.getBytes();
System.out.println(bytes); // [97, 98, 99, 100, 101, 102, 103, -16, -97, -104, -96]

12.boolean equals(Object anObject)

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

将此字符串与指定对象进行比较。当且仅当参数不为空,并且参数与此对象的字符序列相同时,返回值为true。 

String s = "abcdefg😠";
String s1 = "abcdefg";
String s2 = "abcdefg😠";
System.out.println(s.equals(s1)); // false
System.out.println(s.equals(s2)); // true

13.boolean contentEquals(StringBuffer sb)

public boolean contentEquals(StringBuffer sb) {
  return contentEquals((CharSequence)sb);
}

将此字符串与指定的StringBuffer进行比较。当且仅当此字符串与指定的StringBuffer的字符序列相同时,返回值为true。

14.boolean contentEquals(CharSequence cs)

public boolean contentEquals(CharSequence cs) {
  // 参数为StringBuffer或StringBuilder
  if (cs instanceof AbstractStringBuilder) {
    if (cs instanceof StringBuffer) {
      synchronized(cs) {
        return nonSyncContentEquals((AbstractStringBuilder)cs);
      }
    } else {
      return nonSyncContentEquals((AbstractStringBuilder)cs);
    }
  }
  // 参数是String
  if (cs instanceof String) {
    return equals(cs);
  }
  // 参数是其他CharSequence子类
  char v1[] = value;
  int n = v1.length;
  if (n != cs.length()) {
    return false;
  }
  for (int i = 0; i < n; i++) {
    if (v1[i] != cs.charAt(i)) {
      return false;
    }
  }
  return true;
}

将此字符串与指定的CharSequence进行比较。当且仅当此字符串与指定的CharSequence有相同的字符值序列时,返回值为true。注意,如果CharSequence是StringBuffer,那么该方法将对其进行同步。 

String s = "abcdefg";
StringBuffer buffer = new StringBuffer("abcdefg");
StringBuilder builder = new StringBuilder("abcdefg");
System.out.println(s.contentEquals(buffer)); // true
System.out.println(s.contentEquals(builder)); // true

15.boolean equalsIgnoreCase(String anotherString)

public boolean equalsIgnoreCase(String anotherString) {
  return (this == anotherString) ? true
      : (anotherString != null)
          && (anotherString.value.length == value.length)
          && regionMatches(true, 0, anotherString, 0, value.length);
}

将此字符串与另一个字符串进行比较,忽略大小写。如果两个字符串的长度相同,且两个字符串中的对应字符忽略大小写相等,则视为相等。 

String s = "abcdefg";
String s1 = "AbcDEfg";
System.out.println(s.equalsIgnoreCase(s1)); // true

16.int compareTo(String anotherString)

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

以字典方式比较两个字符串。比较基于字符串中每个字符的Unicode值。逐位比较字符的Unicode值,当出现不相等的Unicode时,返回两个Unicode差值,否则返回两个字符串长度的差值。当返回值小于0时表示此字符串小于参数字符串;当返回值等于0时表示此字符串与参数字符串相等0;当返回值大于0时表示此字符串大于参数字符串。

String s = "abcdefg";
String s1 = "AbcDEfg";
String s2 = "abce";
String s3=  "abcdef";
String s4=  "abcdefg";
// 比较结果 > 0 表示字符串s比后面的字符串大
// < 0 表示字符串s比后面的字符串小
// == 0 表示字符串s与后面的字符串相等
System.out.println(s.compareTo(s1)); // 32 'a' > 'A'
System.out.println(s.compareTo(s2)); // -1 虽然s2.length() < s.length() 但是第四个字符'e' > 'd',所以s2比s大
System.out.println(s.compareTo(s3)); // 1
System.out.println(s.compareTo(s4)); // 0

17.int compareToIgnoreCase(String str)

public int compareToIgnoreCase(String str) {
  return CASE_INSENSITIVE_ORDER.compare(this, str);
}

 忽略大小写的比较。

String s = "abcdefg";
String s1 = "AbcDEfg";
String s2 = "abce";
String s3=  "abcdef";
String s4=  "abcdefg";
System.out.println(s.compareToIgnoreCase(s1)); // 0
System.out.println(s.compareToIgnoreCase(s2)); // -1
System.out.println(s.compareToIgnoreCase(s3)); // 1
System.out.println(s.compareToIgnoreCase(s4)); // 0

18.boolean regionMatches(int toffset, String other, int ooffset, int len)

public boolean regionMatches(int toffset, String other, int ooffset,
    int len) {
  char ta[] = value;
  int to = toffset;
  char pa[] = other.value;
  int po = ooffset;
  // Note: toffset, ooffset, or len might be near -1>>>1.
  if ((ooffset < 0) || (toffset < 0)
      || (toffset > (long)value.length - len)
      || (ooffset > (long)other.value.length - len)) {
    return false;
  }
  while (len-- > 0) {
    if (ta[to++] != pa[po++]) {
      return false;
    }
  }
  return true;
}

测试两个字符串区域是否相等。

将此String对象的子字符串与参数other的子字符串进行比较。如果这些子字符串表示相同的字符序列,则结果为真。要比较的此String对象的子字符串从索引toffset开始,长度为len。要比较的other的子字符串从索引ooffset开始,长度为len。

19.boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)

public boolean regionMatches(boolean ignoreCase, int toffset,
    String other, int ooffset, int len) {
  char ta[] = value;
  int to = toffset;
  char pa[] = other.value;
  int po = ooffset;
  // 注意:toffset、ooffset、len的值可能接近 -1 >>> 1 的值。
  if ((ooffset < 0) || (toffset < 0)
      || (toffset > (long)value.length - len)
      || (ooffset > (long)other.value.length - len)) {
    return false;
  }
  while (len-- > 0) {
    char c1 = ta[to++];
    char c2 = pa[po++];
    if (c1 == c2) {
      continue;
    }
    if (ignoreCase) {
      // 将每个字符转换为大写进行比较
      char u1 = Character.toUpperCase(c1);
      char u2 = Character.toUpperCase(c2);
      if (u1 == u2) {
        continue;
      }
      // Georgian alphabet大小写转换规则与众不同,需要再次转换为小写进行比较
      if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
        continue;
      }
    }
    return false;
  }
  return true;
}

测试两个字符串区域是否相等。 

20.boolean startsWith(String prefix, int toffset)

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;
  // 注意:toffset 的值可能接近 -1 >>> 1 的值。
  if ((toffset < 0) || (toffset > value.length - pc)) {
    return false;
  }
  while (--pc >= 0) {
    if (ta[to++] != pa[po++]) {
      return false;
    }
  }
  return true;
}

测试此字符串的以指定索引开头的子字符串是否以指定前缀开头。 

String s = "abcdefg";
System.out.println(s.startsWith("a")); // true

21.boolean startsWith(String prefix)

public boolean startsWith(String prefix) {
  return startsWith(prefix, 0);
}

测试此字符串是否以指定前缀开头。 

String s = "😠abcdefg";
System.out.println(s.startsWith("😠")); // true
System.out.println(s.startsWith("\uD83D\uDE20")); // true
System.out.println(s.startsWith("\uD83D")); // true

22.boolean endsWith(String suffix)

public boolean endsWith(String suffix) {
  return startsWith(suffix, value.length - suffix.value.length);
}

测试此字符串是否以指定后缀结尾。 

String s = "abcdefg😠";
System.out.println(s.endsWith("😠")); // true
System.out.println(s.endsWith("\uD83D\uDE20")); // true
System.out.println(s.endsWith("\uDE20")); // true
s = "abcdefg";
System.out.println(s.endsWith("g")); // true

23.int hashCode()

public int hashCode() {
  int h = hash;
  if (h == 0 && value.length > 0) {
    char val[] = value;

    for (int i = 0; i < value.length; i++) {
      h = 31 * h + val[i];
    }
    hash = h;
  }
  return h;
}

返回此字符串的哈希代码。String对象的哈希代码计算为s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

String s = "abcdefg";
System.out.println(s.hashCode()); // -1206291356

24.int indexOf(int ch)

public int indexOf(int ch) {
  return indexOf(ch, 0);
}

返回此字符串中第一个出现的指定字符的索引。如果值为ch的字符出现在此String对象表示的字符序列中,则返回第一次出现的索引(以Unicode代码单位表示)。对于范围从0到0xFFFF(含)的ch值,这是最小值k,因此: this.charAt(k) == ch为true。对于ch的其他值,它是最小值k,这样:this.codePointAt(k) == ch为true。如果此字符串中没有出现此类字符,则返回-1。

String s = "abcdefg";
System.out.println(s.indexOf(98)); // 1

25.int indexOf(int ch, int fromIndex)

public int indexOf(int ch, int fromIndex) {
  final int max = value.length;
  if (fromIndex < 0) {
    fromIndex = 0;
  } else if (fromIndex >= max) {
    // 注意:fromIndex 的值可能接近 -1 >>> 1的值。
    return -1;
  }

  if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
    // 处理大部分情况:ch是BMP码点或ch是负值(无效码点)
    final char[] value = this.value;
    for (int i = fromIndex; i < max; i++) {
      if (value[i] == ch) {
        return i;
      }
    }
    return -1;
  } else {
    return indexOfSupplementary(ch, fromIndex);
  }
}

返回此字符串中第一个出现的指定字符的索引,从指定索引开始搜索。 

String s = "abcdefg";
System.out.println(s.indexOf(98, 1)); // 1

26.int lastIndexOf(int ch)

public int lastIndexOf(int ch) {
  return lastIndexOf(ch, value.length - 1);
}

返回此字符串中指定字符最后一次出现的索引。 

String s = "abcdebfg";
System.out.println(s.lastIndexOf(98)); // 5

27.int lastIndexOf(int ch, int fromIndex)

public int lastIndexOf(int ch, int fromIndex) {
  if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
    // 处理大部分情况:ch是BMP码点或负值(无效码点)
    final char[] value = this.value;
    int i = Math.min(fromIndex, value.length - 1);
    for (; i >= 0; i--) {
      if (value[i] == ch) {
        return i;
      }
    }
    return -1;
  } else {
    return lastIndexOfSupplementary(ch, fromIndex);
  }
}

返回此字符串中指定字符最后一次出现的索引,从指定索引开始向后搜索。对于范围从0到0xFFFF(含)的ch值,返回的索引是最大值k:(this.charAt(k)==ch) && (k<=fromIndex)为true。对于ch的其他值,它是最大值k:(this.codePointAt(k)==ch) && (k<=fromIndex)为true。在这两种情况下,如果此字符串中fromIndex位置或之前没有出现此类字符,则返回-1。

String s = "abcdebfg";
System.out.println(s.lastIndexOf(98, 4)); // 1

28. int indexOf(String str)

public int indexOf(String str) {
  return indexOf(str, 0);
}

返回此字符串中指定子字符串第一次出现的索引。返回的索引是最小值k,其中:this.startsWith(str, k)。如果不存在这样的k值,则返回-1。

String s = "abcdebfg";
System.out.println(s.indexOf("b")); // 1

29.int indexOf(String str, int fromIndex)

public int indexOf(String str, int fromIndex) {
  return indexOf(value, 0, value.length,
      str.value, 0, str.value.length, fromIndex);
}

返回此字符串中指定子字符串第一次出现的索引,从指定索引开始。返回的索引是最小值k,其中:k>=fromIndex&&this.startsWith(str, k)。如果不存在这样的k值,则返回-1。

String s = "abcdebfg";
System.out.println(s.indexOf("b", 2)); // 5

30.int lastIndexOf(String str) 

public int lastIndexOf(String str) {
  return lastIndexOf(str, value.length);
}

返回此字符串中指定子字符串最后一次出现的索引。空字符串的最后一次出现被认为出现在索引值this.length()处。 

String s = "abcdebfg";
System.out.println(s.lastIndexOf("b")); // 5

31.int lastIndexOf(String str, int fromIndex)

public int lastIndexOf(String str, int fromIndex) {
  return lastIndexOf(value, 0, value.length,
      str.value, 0, str.value.length, fromIndex);
}

返回此字符串中指定子字符串最后一次出现的索引,从指定索引开始向后搜索。

String s = "abcdebfg";
System.out.println(s.lastIndexOf("b", 3)); // 1

32.String substring(int beginIndex)

public String substring(int beginIndex) {
  if (beginIndex < 0) {
    throw new StringIndexOutOfBoundsException(beginIndex);
  }
  int subLen = value.length - beginIndex;
  if (subLen < 0) {
    throw new StringIndexOutOfBoundsException(subLen);
  }
  return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

返回此字符串的子字符串。子字符串以指定索引处的字符开头,并延伸到此字符串的结尾。

String s = "abcdebfg";
System.out.println(s.substring(1)); // bcdebfg

33.String substring(int beginIndex, int endIndex)

public String substring(int beginIndex, int endIndex) {
  if (beginIndex < 0) {
    throw new StringIndexOutOfBoundsException(beginIndex);
  }
  if (endIndex > value.length) {
    throw new StringIndexOutOfBoundsException(endIndex);
  }
  int subLen = endIndex - beginIndex;
  if (subLen < 0) {
    throw new StringIndexOutOfBoundsException(subLen);
  }
  return ((beginIndex == 0) && (endIndex == value.length)) ? this
      : new String(value, beginIndex, subLen);
}

返回此字符串的子字符串。子字符串从指定的beginIndex开始,并扩展到索引endIndex-1处的字符。因此,子字符串的长度是endIndex - beginIndex。 

String s = "abcdebfg";
System.out.println(s.substring(1, 3)); // bc

34.CharSequence subSequence(int beginIndex, int endIndex)

public CharSequence subSequence(int beginIndex, int endIndex) {
  return this.substring(beginIndex, endIndex);
}

返回作为此字符串的子字符序列。 

35.String concat(String str)

public String concat(String str) {
  if (str.isEmpty()) {
    return this;
  }
  int len = value.length;
  int otherLen = str.length();
  char buf[] = Arrays.copyOf(value, len + otherLen);
  str.getChars(buf, len);
  return new String(buf, true);
}

将指定的字符串连接到此字符串的结尾。 

System.out.println("abcd".concat("ef")); // abcdef
System.out.println("abcd\uD83D".concat("\uDE20ef")); // abcd😠ef
System.out.println("abcd\uD83D".concat("ef\uDE20")); // abcd?ef?

36.String replace(char oldChar, char newChar)

public String replace(char oldChar, char newChar) {
  if (oldChar != newChar) {
    int len = value.length;
    int i = -1;
    char[] val = value; /* avoid getfield opcode */

    while (++i < len) {
      if (val[i] == oldChar) {
        break;
      }
    }
    if (i < len) {
      char buf[] = new char[len];
      for (int j = 0; j < i; j++) {
        buf[j] = val[j];
      }
      while (i < len) {
        char c = val[i];
        buf[i] = (c == oldChar) ? newChar : c;
        i++;
      }
      return new String(buf, true);
    }
  }
  return this;
}

返回一个字符串,该字符串是用newChar替换此字符串中所有oldChar的结果。 

String s = "aaaabbbbccdefaaabcd";
System.out.println(s.replace('a', 'x')); // xxxxbbbbccdefxxxbcd

37.boolean matches(String regex)

public boolean matches(String regex) {
  return Pattern.matches(regex, this);
}

检测此字符串是否与给定的正则表达式匹配。 

String s = "abcdefg";
System.out.println(s.matches(".*[0-9].*")); // false
System.out.println(s.matches(".*[a-z].*")); // true
System.out.println(s.matches(".*[A-Z].*")); // false

38.boolean contains(CharSequence s)

public boolean contains(CharSequence s) {
  return indexOf(s.toString()) > -1;
}

当且仅当此字符串包含指定的字符值序列时,返回true。 

String s = "abcdefg😠";
System.out.println(s.contains("a")); // true
System.out.println(s.contains("z")); // false
System.out.println(s.contains("\uD83D")); // true
System.out.println(s.contains("\uDE20")); // true

39.String replaceFirst(String regex, String replacement)

public String replaceFirst(String regex, String replacement) {
  return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}

用给定的字符串替换此字符串中与给定正则表达式匹配的第一个子字符串。 

String s = "abcdefg";
System.out.println(s.replaceFirst("[a-z]", "z")); // zbcdefg
System.out.println(s.replaceFirst(".*[a-z].*", "z")); // z

40.String replaceAll(String regex, String replacement)

public String replaceAll(String regex, String replacement) {
  return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}

用给定的字符串替换此字符串中与给定正则表达式匹配的每个子字符串。 

String s = "abcdefg";
System.out.println(s.replaceAll("[a-z]", "z")); // zzzzzzz
System.out.println(s.replaceAll(".*[a-z].*", "z")); // z

41.String replace(CharSequence target, CharSequence replacement)

public String replace(CharSequence target, CharSequence replacement) {
  return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
      this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}

用指定的文字序列替换此字符串中与文字目标序列匹配的每个子字符串。替换从字符串的开头进行到结尾,例如,将字符串“aaa”中的“aa”替换为“b”将导致“ba”而不是“ab”。 

String s = "abcabcabcdddeeefff";
System.out.println(s.replace("abc", "zzz")); // zzzzzzz
s = "bbabbb";
System.out.println(s.replace("bb", "z")); // zazb

42.String[] split(String regex, int limit)

public String[] split(String regex, int limit) {
      /* fastpath
       (1)如果regex是一个字符,并且不是".$|()[{^?*+\\"中的任意字符
       (2)如果regex是两个字符,并且第一个字符是反斜杠,第二个字符不是数字或者字母
       */
  char ch = 0;
  if (((regex.value.length == 1 &&
      ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
      (regex.length() == 2 &&
          regex.charAt(0) == '\\' &&
          (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
          ((ch-'a')|('z'-ch)) < 0 &&
          ((ch-'A')|('Z'-ch)) < 0)) &&
      (ch < Character.MIN_HIGH_SURROGATE ||
          ch > Character.MAX_LOW_SURROGATE))
  {
    int off = 0;
    int next = 0;
    boolean limited = limit > 0;
    ArrayList<String> list = new ArrayList<>();
    while ((next = indexOf(ch, off)) != -1) {
      if (!limited || list.size() < limit - 1) {
        list.add(substring(off, next));
        off = next + 1;
      } else {    // 最后一项
        //assert (list.size() == limit - 1);
        list.add(substring(off, value.length));
        off = value.length;
        break;
      }
    }
    // 如果没有匹配到,则返回自身
    if (off == 0)
      return new String[]{this};

    // 添加剩余部分
    if (!limited || list.size() < limit)
      list.add(substring(off, value.length));

    // Construct result
    int resultSize = list.size();
    if (limit == 0) {
      while (resultSize > 0 && list.get(resultSize - 1).isEmpty()) {
        resultSize--;
      }
    }
    String[] result = new String[resultSize];
    return list.subList(0, resultSize).toArray(result);
  }
  return Pattern.compile(regex).split(this, limit);
}

使用给定正则表达式的匹配项拆分此字符串。

String s = "a,b,c,d";
System.out.println(s.split(",", 2)); // ["a", "b,c,d"]

 43.String[] split(String regex)

public String[] split(String regex) {
  return split(regex, 0);
}

使用给定正则表达式的匹配项拆分此字符串。 

String s = "a,b,c,d";
System.out.println(s.split(",")); // ["a", "b", "c", "d"]
s = "1a2b3c4d";
System.out.println(s.split("[a-z]")); // ["1", "2", "3", "4"]
System.out.println(s.split("[a-z].*")); // ["1"]
System.out.println(s.split(".*[a-z].*")); // []
System.out.println(s.split(".*[a-z]")); // []

44.String join(CharSequence delimiter, CharSequence... elements)

public static String join(CharSequence delimiter, CharSequence... elements) {
  Objects.requireNonNull(delimiter);
  Objects.requireNonNull(elements);
  // Number of elements not likely worth Arrays.stream overhead.
  StringJoiner joiner = new StringJoiner(delimiter);
  for (CharSequence cs: elements) {
    joiner.add(cs);
  }
  return joiner.toString();
}

返回一个新字符串,该字符串由CharSequence元素的副本与指定分隔符的副本连接在一起组成。 

String s = String.join(",", "a", "b", "c");
System.out.println(s); // a,b,c

45.String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

public static String join(CharSequence delimiter,
    Iterable<? extends CharSequence> elements) {
  Objects.requireNonNull(delimiter);
  Objects.requireNonNull(elements);
  StringJoiner joiner = new StringJoiner(delimiter);
  for (CharSequence cs: elements) {
    joiner.add(cs);
  }
  return joiner.toString();
}

返回一个新字符串,该字符串由CharSequence元素的副本与指定分隔符的副本连接在一起组成。 

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
String s = String.join(",", list);
System.out.println(s); // a,b,c

46.String toLowerCase(Locale locale)

public String toLowerCase(Locale locale) {
  if (locale == null) {
    throw new NullPointerException();
  }

  int firstUpper;
  final int len = value.length;

  /* 检查是否有需要更改的字符。 */
  scan: {
    for (firstUpper = 0 ; firstUpper < len; ) {
      char c = value[firstUpper];
      if ((c >= Character.MIN_HIGH_SURROGATE)
          && (c <= Character.MAX_HIGH_SURROGATE)) {
        int supplChar = codePointAt(firstUpper);
        if (supplChar != Character.toLowerCase(supplChar)) {
          break scan;
        }
        firstUpper += Character.charCount(supplChar);
      } else {
        if (c != Character.toLowerCase(c)) {
          break scan;
        }
        firstUpper++;
      }
    }
    return this;
  }

  char[] result = new char[len];
  int resultOffset = 0;  /* result可能会增长,因此i+resultOffset是result中的写入位置 */

  /* 只需复制前几个小写字符。 */
  System.arraycopy(value, 0, result, 0, firstUpper);

  String lang = locale.getLanguage();
  boolean localeDependent =
      (lang == "tr" || lang == "az" || lang == "lt");
  char[] lowerCharArray;
  int lowerChar;
  int srcChar;
  int srcCount;
  for (int i = firstUpper; i < len; i += srcCount) {
    srcChar = (int)value[i];
    if ((char)srcChar >= Character.MIN_HIGH_SURROGATE
        && (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
      srcChar = codePointAt(i);
      srcCount = Character.charCount(srcChar);
    } else {
      srcCount = 1;
    }
    if (localeDependent ||
        srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
        srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
      lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
    } else {
      lowerChar = Character.toLowerCase(srcChar);
    }
    if ((lowerChar == Character.ERROR)
        || (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
      if (lowerChar == Character.ERROR) {
        lowerCharArray =
            ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
      } else if (srcCount == 2) {
        resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
        continue;
      } else {
        lowerCharArray = Character.toChars(lowerChar);
      }

      /* Grow result if needed */
      int mapLen = lowerCharArray.length;
      if (mapLen > srcCount) {
        char[] result2 = new char[result.length + mapLen - srcCount];
        System.arraycopy(result, 0, result2, 0, i + resultOffset);
        result = result2;
      }
      for (int x = 0; x < mapLen; ++x) {
        result[i + resultOffset + x] = lowerCharArray[x];
      }
      resultOffset += (mapLen - srcCount);
    } else {
      result[i + resultOffset] = (char)lowerChar;
    }
  }
  return new String(result, 0, len + resultOffset);
}

使用给定区域设置的规则将此字符串中的所有字符转换为小写。 

String s = "ABCDEFG";
System.out.println(s.toLowerCase(Locale.ROOT)); // abcdefg

47.String toLowerCase()

public String toLowerCase() {
  return toLowerCase(Locale.getDefault());
}

使用默认区域设置的规则将此字符串中的所有字符转换为小写。这相当于调用toLowerCase(Locale.getDefault())。 

String s = "ABCDEFG";
System.out.println(s.toLowerCase()); // abcdefg

48.String toUpperCase(Locale locale)

public String toUpperCase(Locale locale) {
  if (locale == null) {
    throw new NullPointerException();
  }

  int firstLower;
  final int len = value.length;

  /* Now check if there are any characters that need to be changed. */
  scan: {
    for (firstLower = 0 ; firstLower < len; ) {
      int c = (int)value[firstLower];
      int srcCount;
      if ((c >= Character.MIN_HIGH_SURROGATE)
          && (c <= Character.MAX_HIGH_SURROGATE)) {
        c = codePointAt(firstLower);
        srcCount = Character.charCount(c);
      } else {
        srcCount = 1;
      }
      int upperCaseChar = Character.toUpperCaseEx(c);
      if ((upperCaseChar == Character.ERROR)
          || (c != upperCaseChar)) {
        break scan;
      }
      firstLower += srcCount;
    }
    return this;
  }

  /* result may grow, so i+resultOffset is the write location in result */
  int resultOffset = 0;
  char[] result = new char[len]; /* may grow */

  /* Just copy the first few upperCase characters. */
  System.arraycopy(value, 0, result, 0, firstLower);

  String lang = locale.getLanguage();
  boolean localeDependent =
      (lang == "tr" || lang == "az" || lang == "lt");
  char[] upperCharArray;
  int upperChar;
  int srcChar;
  int srcCount;
  for (int i = firstLower; i < len; i += srcCount) {
    srcChar = (int)value[i];
    if ((char)srcChar >= Character.MIN_HIGH_SURROGATE &&
        (char)srcChar <= Character.MAX_HIGH_SURROGATE) {
      srcChar = codePointAt(i);
      srcCount = Character.charCount(srcChar);
    } else {
      srcCount = 1;
    }
    if (localeDependent) {
      upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
    } else {
      upperChar = Character.toUpperCaseEx(srcChar);
    }
    if ((upperChar == Character.ERROR)
        || (upperChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
      if (upperChar == Character.ERROR) {
        if (localeDependent) {
          upperCharArray =
              ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
        } else {
          upperCharArray = Character.toUpperCaseCharArray(srcChar);
        }
      } else if (srcCount == 2) {
        resultOffset += Character.toChars(upperChar, result, i + resultOffset) - srcCount;
        continue;
      } else {
        upperCharArray = Character.toChars(upperChar);
      }

      /* Grow result if needed */
      int mapLen = upperCharArray.length;
      if (mapLen > srcCount) {
        char[] result2 = new char[result.length + mapLen - srcCount];
        System.arraycopy(result, 0, result2, 0, i + resultOffset);
        result = result2;
      }
      for (int x = 0; x < mapLen; ++x) {
        result[i + resultOffset + x] = upperCharArray[x];
      }
      resultOffset += (mapLen - srcCount);
    } else {
      result[i + resultOffset] = (char)upperChar;
    }
  }
  return new String(result, 0, len + resultOffset);
}

使用给定区域设置的规则将此字符串中的所有字符转换为大写。 

String s = "abcdefg";
System.out.println(s.toUpperCase(Locale.getDefault())); // ABCDEFG

49.String toUpperCase()

public String toUpperCase() {
  return toUpperCase(Locale.getDefault());
}

使用默认区域设置的规则将此字符串中的所有字符转换为大写。此方法等效于toUpperCase(Locale.getDefault())。 

String s = "abcdefg";
System.out.println(s.toUpperCase()); // ABCDEFG

50.String trim()

public String trim() {
  int len = value.length;
  int st = 0;
  char[] val = value;    /* avoid getfield opcode */

  while ((st < len) && (val[st] <= ' ')) {
    st++;
  }
  while ((st < len) && (val[len - 1] <= ' ')) {
    len--;
  }
  return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

返回一个值为该字符串的字符串,并删除所有前导和尾随空格。 

String s = " abcdefg  \n";
System.out.println(s.trim()); // abcdefg

51.String toString()

public String toString() {
  return this;
}

此对象(已经是字符串!)本身被返回。 

52.char[] toCharArray()

public char[] toCharArray() {
  // Cannot use Arrays.copyOf because of class initialization order issues
  char result[] = new char[value.length];
  System.arraycopy(value, 0, result, 0, value.length);
  return result;
}

将此字符串转换为新的字符数组。

String s = "abcdefg";
System.out.println(s.toCharArray()); // [a, b, c, d, e, f, g]
s = "abcdefg😠";
System.out.println(s.toCharArray()); // [a, b, c, d, e, f, g, \uD83D, \uDE20]

53.String format(String format, Object... args)

public static String format(String format, Object... args) {
  return new Formatter().format(format, args).toString();
}

使用指定的格式字符串和参数返回格式化字符串。 

String s = "str=%b";
System.out.println(String.format(s, true)); // str=true
s = "str=%2$5b and str2=%1$5b"; // %2表示第二个参数,这里是false,$5表示占用五个字符,不足五个字符的话左侧补空格,b表示boolean类型
System.out.println(String.format(s, true, false)); // str=false and str2= true

54.String format(Locale l, String format, Object... args)

public static String format(Locale l, String format, Object... args) {
  return new Formatter(l).format(format, args).toString();
}

使用指定的区域设置、格式字符串和参数返回格式化字符串。 

55.String valueOf(Object obj)

public static String valueOf(Object obj) {
  return (obj == null) ? "null" : obj.toString();
}

返回Object参数的字符串表示形式。

56.String valueOf(char data[])

public static String valueOf(char data[]) {
  return new String(data);
}

返回char数组参数的字符串表示形式。复制字符数组的内容;字符数组的后续修改不会影响返回的字符串。 

57.String valueOf(char data[], int offset, int count)

public static String valueOf(char data[], int offset, int count) {
  return new String(data, offset, count);
}

返回char数组参数的特定子数组的字符串表示形式。 

58.String copyValueOf(char data[], int offset, int count)

public static String copyValueOf(char data[], int offset, int count) {
  return new String(data, offset, count);
}

等效于valueOf(char[], int, int)。 

59.String copyValueOf(char data[])

public static String copyValueOf(char data[]) {
  return new String(data);
}

等效于valueOf(char[])。 

60.String valueOf(boolean b)

public static String valueOf(boolean b) {
  return b ? "true" : "false";
}

返回布尔参数的字符串表示形式。 

61.String valueOf(char c)

public static String valueOf(char c) {
  char data[] = {c};
  return new String(data, true);
}

返回char参数的字符串表示形式。

62.String valueOf(int i)

public static String valueOf(int i) {
  return Integer.toString(i);
}

返回int参数的字符串表示形式。 

63.String valueOf(long l)

public static String valueOf(long l) {
  return Long.toString(l);
}

返回long参数的字符串表示形式。 

64.String valueOf(float f)

public static String valueOf(float f) {
  return Float.toString(f);
}

返回float参数的字符串表示形式。 

65.String valueOf(double d)

public static String valueOf(double d) {
  return Double.toString(d);
}

返回double参数的字符串表示形式。 

66.String intern()

public native String intern();

如果字符常量池中已经包含一个等于此String对象的字符串,则返回常量池中字符串的引用,否则将新的字符串放入常量池,并返回新字符串的引用。

String s = new String("s");
String s1 = new String("s");
String s2 = s.intern();
String s3 = new String("s");
String s4 = "s";
String s5 = s4.intern();
String s6 = "s";
System.out.println(s == s1); // false
System.out.println(s == s2); // false
System.out.println(s == s3); // false
System.out.println(s == s4); // false
System.out.println(s4 == s5); // true
System.out.println(s4 == s6); // true

常见问题

JDK源码当中有多处 might be near -1>>>1 的注释,这个是什么意思?

// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
  throw new StringIndexOutOfBoundsException(offset + count);
}

这里的意思是offset或者count的值可能都接近 -1>>>1的值(Integer.MAX_VALUE)。如果判断条件改写成 if (offset + count > value.length) 的话,就有可能会溢出。此时 offset + count < value.length。举个例子:

System.out.println(-1 >>> 1 == Integer.MAX_VALUE); // true
int i = 1;
int j = Integer.MAX_VALUE - 10;
int n = Integer.MAX_VALUE - 100;
System.out.println(n + j); // -112
System.out.println(n + j > i); // false

为什么 -1>>>1 的值是Integer.MAX_VALUE?

int在内存中占用4个字节,所以int为32位,那么1的原码为:0000 0000 0000 0000 0000 0000 0000 0001,将符号位以及其他各位全部取反为:1111 1111 1111 1111 1111 1111 1111 1110,然后再加1为:1111 1111 1111 1111 1111 1111 1111 1111。此时这个值即为-1,再对-1无符号右移1位,此时即为0111 1111 1111 1111 1111 1111 1111 1111,这个值就是JDK源码当中的0x7fffffff,即为Integer.MAX_VALUE。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值