Java 中 String 类的方法总结

498 阅读41分钟

1. 替换:replace、replaceAll、replaceFirst

字符串替换方法

public String replace(char oldChar, char newChar) {...}
public String replace(CharSequence target, CharSequence replacement) {...}
public String replaceAll(String regex, String replacement) {...}
public String replaceFirst(String regex, String replacement) {...}

(1)两个 replace 方法的区别

replace(char oldChar, char newChar):接受和替换的都是单个字符。只能替换单个字符。适用于替换单个字符的场景。

replace(CharSequence target, CharSequence replacement):接受和替换的是字符序列(CharSequence),可以是字符串或其他实现了CharSequence接口的对象。可以替换任意长度的字符序列,包括字符串。适用于替换字符串或更复杂的字符序列的场景。

String str = "hello world";

String newStr1 = str.replace('o', '0');
System.out.println(newStr1);  // 输出: hell0 w0rld

String newStr2 = str.replace("world", "Java");
System.out.println(newStr2);  // 输出: hello Java

(2)replace 和 replaceAll、replaceFirst 方法的区别

参数区别

replace 方法的参数类型有 charCharSequence,既可以支持字符的替换,也可以支持字符串的替换(CharSequence 即字符序列的意思,说白了也就是字符串);

replaceAllreplaceFirst的形式参数是 regex,基于正则表达式的替换。比如,可以通过 replaceAll ("\d", "*") 把一个字符串所有的数字字符都换成星号;

String 类执行了替换操作后,返回一个新的对象,源字符串的内容是没有发生改变的。

使用区别

replace()replaceAll() 都是常用的替换字符串的方法;两者都是全部替换,可以把源字符串中的某一字符或字符串全部换成指定的字符或字符串;

如果只想替换第一次出现的,可以使用 replaceFirst()方法;这个方法也是基于正则表达式的替换,但与 replaceAll()不同的是,只替换第一次出现的字符串

replaceAll()replaceFirst() 所用的替换参数可以是普通字符串,也可以是正则表达式;如果 replaceAll()所用的参数不是基于正则表达式的,和replace()方法效果是一样的,一般会建议使用replace()方法。

String str = "Aoc.Iop.Aoc.Iop.Aoc";

String str1 = str.replace(".", "#");
//Aoc#Iop#Aoc#Iop#Aoc
System.out.println(str1);

String str2 = str.replaceAll(".", "#");
//###################
System.out.println(str2);

String str3 = str.replaceFirst(".", "#");
//#oc.Iop.Aoc.Iop.Aoc
System.out.println(str3);

2. 拆分:split

字符串拆分方法

public String[] split(String regex) {...} 
public String[] split(String regex, int limit) {...}

split(String regex):这个方法将字符串按照给定的正则表达式 regex 进行分割,并返回一个包含所有子字符串的数组(尾随空字符串将被丢弃)。如果字符串不包含与正则表达式匹配的子字符串,则返回的数组只包含一个元素,即原始字符串。适用于不需要限制分割次数的场景。

split(String regex, int limit):这个方法也将字符串按照给定的正则表达式 regex 进行分割,但可以指定一个限制参数 limit 来控制分割的次数或结果数组的长度。适用于需要限制分割次数或想要控制结果数组长度的场景。例如,当你只想分割前几个部分,或者想要保留最后一部分不被分割时,这个方法非常有用。

如果 limit 大于 0,则模式将被最多应用 limit-1 次,数组的长度不会超过 limit,而且数组的最后一个元素将包含超出最后匹配的定界符的所有输入。

如果 limit 小于 0,则模式将被应用尽可能多的次数,数组可以有任何长度。

如果 limit 为 0,则模式将被应用尽可能多的次数,数组可以有任何长度,并且尾随空字符串将被丢弃。等同于没有 limit 参数的情况。

String str = "one-two--three---";
// 不限制分割次数,尾随空字符串被丢弃
String[] split = str.split("-");
System.out.println(Arrays.asList(split));//[one, two, , three]
// 使用非正的limit值(例如0),尾随空字符串被丢弃
String[] parts = str.split("-", 0);
System.out.println(Arrays.toString(parts));//[one, two, , three]
// 使用负数作为limit(例如-3)
String[] parts1 = str.split("-", -3);
System.out.println(Arrays.toString(parts1));//[one, two, , three, , , ]
// 限制分割次数为3
String[] parts2 = str.split("-", 3);
System.out.println(Arrays.toString(parts2));//[one, two, -three---]

3. 截取:substring、subSequence、getChars

字符串截取方法

public String substring(int beginIndex) {...} 
public String substring(int beginIndex, int endIndex) {...} 
public CharSequence subSequence(int beginIndex, int endIndex) {...}
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {...}

注意事项,参数 index 是从 0 开始,并且是前闭后开,也就是包括 beginIndex,不包括 endIndex。

substring(int beginIndex)‌:这个方法返回一个新的字符串,该字符串是此字符串的一个子字符串。子字符串从指定的 beginIndex 开始,直到字符串的末尾。

substring(int beginIndex, int endIndex)‌:这个方法也返回一个新的字符串,但是这次子字符串是从 beginIndex 开始,直到索引 endIndex-1 处的字符。也就是说,endIndex 是子字符串结束后的下一个索引,而不是子字符串的一部分。

subSequence(int beginIndex, int endIndex)‌:这个方法返回一个 CharSequence,它是此序列的一个子序列。子序列从 beginIndex 开始,直到索引 endIndex-1 处的字符。CharSequence 是一个接口,String 类实现了这个接口,所以这个方法实际上也可以返回一个 String 类型的对象,但更一般地,它返回的是一个 CharSequence。

String str = "Hello, World!";

String subStr = str.substring(7); // "World!"

String subStr = str.substring(7, 12); // "World"

CharSequence subSeq = str.subSequence(7, 12); // "World"
//在这个例子中,subSeq 实际上是一个 String,包含从索引 7(包括)到索引 11(不包括)的所有字符。

需要注意的是,这三个方法中的索引都是从 0 开始的,且如果 beginIndex 是负数,或者 beginIndex 大于字符串的长度,或者 beginIndex 大于 endIndex(对于需要两个索引的方法),都会抛出 StringIndexOutOfBoundsException 异常。在使用这些方法时,务必确保提供的索引是有效的。

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

参数解释:

  • srcBegin:源字符串中要复制的起始字符的索引(包含),索引从 0 开始。
  • srcEnd:源字符串中要复制的结束字符的索引(不包含),也就是说,复制操作会在到达这个索引之前停止。
  • dst:目标字符数组,用于存储从源字符串中复制出来的字符。
  • dstBegin:目标字符数组中开始存储复制字符的位置的索引。

这个方法不会返回任何值(它的返回类型是 void),而是直接修改传入的目标字符数组。

使用 getChars 方法时,需要注意以下几点:

  • 索引范围:srcBegin 必须小于等于 srcEnd,且 srcEnd 不能大于源字符串的长度。否则,会抛出 StringIndexOutOfBoundsException 异常。
  • 数组空间:目标字符数组 dst 必须有足够的空间来存储从源字符串中复制出来的字符。具体来说,从 dstBegin 开始,dst 数组至少应该有 (srcEnd - srcBegin) 个空位。如果空间不足,会抛出 ArrayIndexOutOfBoundsException 异常。
  • 字符复制:复制操作是逐字符进行的,从源字符串的 srcBegin 索引开始,直到 srcEnd 索引之前(不包含 srcEnd 索引对应的字符)。
String source = "Hello, World!";
char[] destination = new char[5];
source.getChars(7, 12, destination, 0);
// 现在,destination 数组包含字符 'W', 'o', 'r', 'l', 'd'
System.out.println(new String(destination)); // 输出 "World"

在这个示例中,我们从源字符串 "Hello, World!" 中复制了子字符串 "World" 到目标字符数组 destination 中。复制操作从源字符串的索引 7 开始(包含 'W'),到索引 12 结束(不包含 '!'),并将结果存储在目标数组的起始位置(索引 0)。

4. 截取(空格):trim、strip、stripLeading、stripTrailing

也是字符串截取方法,只不过是去除前后空格

public String trim() {...}
public String strip() {...} 
public String stripLeading() {...} 
public String stripTrailing() {...} 

在 String 类中,trim() 方法是一个非常重要的实例方法,它的主要作用是去除字符串两端的空白字符,并返回一个新的字符串。这里的“空白字符”通常指的是空格字符(' ')、制表符(\t)、换行符(\n)、回车符(\r)等。

‌trim() 方法会检查当前字符串的两端,并去除所有连续的空白字符。它不会修改原始字符串,而是返回一个新的字符串,该字符串是去除两端空白后的结果。字符串中间的空白字符不会受到影响,它们会被保留在新字符串中。

public class StringTrimExample {
    public static void main(String[] args) {
        String originalString = "   Hello, World!   ";
        String trimmedString = originalString.trim();
        
        System.out.println("Original String: \"" + originalString + "\"");//Original String: "   Hello, World!   "
        System.out.println("Trimmed String: \"" + trimmedString + "\"");//Trimmed String: "Hello, World!"
    }
}

在 Java 11 及更高版本中,String 类引入了三个新的方法来处理字符串两端的空白字符:strip()、stripLeading() 和 stripTrailing()。这些方法提供了比传统的 trim() 方法更灵活和清晰的方式来去除字符串中的空白。

public String strip()

strip() 方法用于去除字符串两端的空白字符。这里的“空白字符”不仅限于空格,还包括制表符(\t)、换行符(\n)、回车符(\r)以及表单符(\f)等。与 trim() 方法不同的是,strip() 更加明确地表达了去除两端空白字符的意图。

‌返回值‌:返回一个新的字符串,该字符串去除了原字符串两端的空白字符。如果原字符串两端没有空白字符,则返回原字符串本身。

public String stripLeading()

stripLeading() 方法仅去除字符串开头的空白字符,而不影响字符串结尾的空白字符。

‌返回值‌:返回一个新的字符串,该字符串去除了原字符串开头的空白字符。如果原字符串开头没有空白字符,则返回原字符串本身。

public String stripTrailing()

stripTrailing() 方法仅去除字符串结尾的空白字符,而不影响字符串开头的空白字符。

‌返回值‌:返回一个新的字符串,该字符串去除了原字符串结尾的空白字符。如果原字符串结尾没有空白字符,则返回原字符串本身。

String str = "  \t Hello, World! \n  ";

// 使用 strip() 方法去除两端空白字符
String stripped = str.strip();
System.out.println("Stripped: '" + stripped + "'"); // 输出: 'Hello, World!'

// 使用 stripLeading() 方法去除开头空白字符
String strippedLeading = str.stripLeading();
System.out.println("Stripped Leading: '" + strippedLeading + "'"); // 输出: 'Hello, World! \n  '

// 使用 stripTrailing() 方法去除结尾空白字符
String strippedTrailing = str.stripTrailing();
System.out.println("Stripped Trailing: '" + strippedTrailing + "'"); // 输出: '  \t Hello, World!'

trim 和 strip 方法的区别

trim() 方法

  • ‌历史‌:trim() 方法自Java早期版本以来就一直存在。
  • ‌功能‌:它去除字符串两端的空白字符,这里的“空白字符”在 Java 的规范中特指空格字符(' ')。尽管在实际实现中,trim() 通常会去除更多类型的空白字符(如制表符、换行符等),但这一行为并不是由 Java 规范直接规定的,而是由具体的 Java 虚拟机(JVM)实现决定的。
  • ‌用途‌:当你只需要去除字符串两端的空格字符,并且不介意可能存在的对其他空白字符的处理不一致性时,可以使用 trim()。

strip() 方法

  • ‌引入‌:strip() 方法是在 Java11 中引入的,作为对 trim() 方法的一个更清晰、更明确的替代。
  • ‌功能‌:它去除字符串两端的所有空白字符,这里的“空白字符”包括空格字符、制表符、换行符、回车符、表单符以及任何其他 Unicode 空白字符。
  • ‌用途‌:当你需要明确地去除字符串两端的所有类型的空白字符时,应该使用 strip()。
String str = "  \t Hello, World! \n  ";

// 使用 trim() 方法
String trimmed = str.trim();
System.out.println("Trimmed: '" + trimmed + "'");
// 输出可能因 JVM 实现而异,但通常会是:'Hello, World!'(假设 JVM 实现了对多种空白字符的去除)

// 使用 strip() 方法
String stripped = str.strip();
System.out.println("Stripped: '" + stripped + "'");
// 输出:'Hello, World!'(明确去除所有空白字符)

在这个示例中,trim() 和 strip() 都去除了字符串两端的空白字符,但由于 strip() 有更明确的规范来定义哪些字符应该被去除,因此它在处理不同类型的空白字符时更加可靠和一致。

总结:如果你正在使用 Java11 或更高版本,并且需要明确地去除字符串两端的所有空白字符,建议使用 strip() 方法。如果你需要保持与旧版 Java 代码的兼容性,或者你的 JVM 实现已经按照你期望的方式处理了 trim() 方法,那么继续使用 trim() 也是可以的。不过,为了代码的可读性和未来的维护性,考虑迁移到 strip() 是一个好主意。

5. 查找:indexOf、lastIndexOf、charAt

字符串查找方法

public int indexOf(int ch) {...} 
public int indexOf(int ch, int fromIndex) {...} 
public int indexOf(String str) {...} 
public int indexOf(String str, int fromIndex) {...} 
public int lastIndexOf(int ch) {...} 
public int lastIndexOf(int ch, int fromIndex) {...} 
public int lastIndexOf(String str) {...} 
public int lastIndexOf(String str, int fromIndex) {...}
public char charAt(int index) {...}

indexOf 方法

public int indexOf(int ch)‌

返回指定字符 ch 在当前字符串中第一次出现的索引。如果字符不存在于字符串中,则返回 -1。

String str = "Hello, World!";
int index = str.indexOf('W'); // 返回 7

public int indexOf(int ch, int fromIndex)‌

从指定的索引 fromIndex 开始(包括该索引),返回字符 ch 在当前字符串中第一次出现的索引。如果字符不存在于从该索引开始的字符串部分中,则返回 -1。

String str = "Hello, World! World!";
int index = str.indexOf('W', 8); // 返回 14,因为从索引 8 开始第一次出现 'W' 是在位置 14。

public int indexOf(String str)‌

返回指定子字符串 str 在当前字符串中第一次出现的索引。如果子字符串不存在于字符串中,则返回 -1。

String str = "Hello, World!";
int index = str.indexOf("World"); // 返回 7

public int indexOf(String str, int fromIndex)‌

从指定的索引 fromIndex 开始(包括该索引),返回子字符串 str 在当前字符串中第一次出现的索引。如果子字符串不存在于从该索引开始的字符串部分中,则返回 -1。

String str = "Hello, World! World!";
int index = str.indexOf("World", 8); // 返回 14,因为从索引 8 开始第一次出现 "World" 是在位置 14。

lastIndexOf 方法

public int lastIndexOf(int ch)‌

返回指定字符 ch 在当前字符串中最后一次出现的索引。如果字符不存在于字符串中,则返回 -1。

String str = "Hello, World! World!";
int index = str.lastIndexOf('W'); // 返回 14,因为'W'最后一次出现在位置14

public int lastIndexOf(int ch, int fromIndex)‌

从指定的索引 fromIndex(包括该索引)开始向前搜索,返回字符 ch 在当前字符串中最后一次出现的索引。如果字符不存在于从该索引开始向前搜索的字符串部分中,则返回 -1。

String str = "Hello, World! World!";
int index = str.lastIndexOf('W', 13); // 返回 7,因为在索引13之前(包括13),'W'最后一次出现在位置7

public int lastIndexOf(String str)‌

返回指定子字符串 str 在当前字符串中最后一次出现的索引。如果子字符串不存在于字符串中,则返回 -1。

String str = "Hello, World! World!";
int index = str.lastIndexOf("World"); // 返回 14,因为"World"最后一次出现在位置14

public int lastIndexOf(String str, int fromIndex)‌

从指定的索引 fromIndex(包括该索引)开始向前搜索,返回子字符串 str 在当前字符串中最后一次出现的索引。如果子字符串不存在于从该索引开始向前搜索的字符串部分中,则返回 -1。

String str = "Hello, World! World!";
int index = str.lastIndexOf("World", 13); // 返回 7,因为在索引13之前(包括13),"World"最后一次出现在位置7

这些方法为在字符串中查找字符或子字符串提供了强大的功能,允许从字符串的开头或指定位置开始搜索,并可以查找第一次或最后一次出现的位置。

public char charAt(int index) {...}

该方法用于返回指定索引处的字符。索引值从 0 开始,即字符串的第一个字符的索引为 0,第二个字符的索引为 1,依此类推。返回‌指定索引处的 char 值。如果 index 为负数,或者大于等于字符串的长度,则抛出 StringIndexOutOfBoundsException。

String str = "Hello, World!";
char ch = str.charAt(7); // 返回 'W'

6. 包含:contains、endsWith、startsWith

字符串包含方法

public boolean contains(CharSequence s) {...} 
public boolean endsWith(String suffix) {...}
public boolean startsWith(String prefix) {...} 
public boolean startsWith(String prefix, int toffset) {...}

public boolean contains(CharSequence s)

检查并返回此字符串是否包含指定的字符序列 s。如果 s 是一个空字符序列(例如""),则总是返回 true,因为任何字符串都包含空字符序列。参数 s 是一个 CharSequence,这意味着它可以是 String 或任何实现了 CharSequence 接口的对象。

String str = "Hello, World!";
boolean result = str.contains("World"); // 返回 true

public boolean endsWith(String suffix)

测试此字符串是否以指定的后缀 suffix 结束。参数 suffix 是一个 String。

String str = "Hello, World!";
boolean result = str.endsWith("World!"); // 返回 true

public boolean startsWith(String prefix)

测试此字符串是否以指定的前缀 prefix 开始。参数 prefix 是一个 String。

String str = "Hello, World!";
boolean result = str.startsWith("Hello"); // 返回 true

public boolean startsWith(String prefix, int toffset)

测试从指定索引 toffset 开始的子字符串是否以指定的前缀 prefix 开始(包含该索引)。参数 toffset 指定了开始比较的索引位置。如果 toffset 是负数,或者大于字符串的长度,将抛出 StringIndexOutOfBoundsException。

String str = "Hello, World!";
boolean result = str.startsWith("World", 7); // 返回 true,因为从索引7开始的子字符串是"World!"

7. 比较:compareTo、equals、contentEquals、regionMatches

字符串比较方法

public int compareTo(String anotherString) {...} 
public int compareToIgnoreCase(String str) {...} 
public boolean equals(Object anObject) {...} 
public boolean equalsIgnoreCase(String anotherString) {...}
public boolean contentEquals(CharSequence cs) {...} 
public boolean contentEquals(StringBuffer sb) {...}
public boolean regionMatches(int toffset, String other, int ooffset, int len) {...} 
public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {...} 

public int compareTo(String anotherString)

按字典顺序比较两个字符串。如果调用对象(即比较中的第一个字符串)与参数字符串 anotherString 相等,则返回0。如果调用对象在字典顺序上位于 anotherString 之前,则返回一个负数。如果调用对象在字典顺序上位于 anotherString 之后,则返回一个正数。比较是基于字符串中各个字符的 Unicode 值进行的。

public int compareToIgnoreCase(String str)

与compareTo方法类似,但是在比较时忽略大小写。同样返回负数、0或正数,表示调用对象在忽略大小写的字典顺序上与参数字符串的比较结果。

public boolean equals(Object anObject)

比较两个字符串的内容是否完全相同。如果调用对象与参数对象 anObject 是同一个对象(即内存地址相同),则返回 true。如果参数对象不是 String 类型,或者两个字符串的长度不同,或者任何对应位置的字符不同,则返回 false。否则,返回true。

public boolean equalsIgnoreCase(String anotherString)

与 equals 方法类似,但是在比较时忽略大小写。如果两个字符串在忽略大小写的情况下内容完全相同,则返回 true;否则返回 false。

示例代码:

String str1 = "Hello";
String str2 = "hello";
String str3 = "Hello";

int comparison = str1.compareTo(str2); // 可能是负数,因为"Hello"在字典顺序上位于"hello"之前(考虑大小写)
int ignoreCaseComparison = str1.compareToIgnoreCase(str2); // 返回0,因为忽略大小写后它们内容相等

boolean isEqual = str1.equals(str2); // 返回false,因为"Hello"不等于"hello"(考虑大小写)
boolean isEqualIgnoreCase = str1.equalsIgnoreCase(str2); // 返回true,因为忽略大小写后它们内容相等
boolean isSameObject = str1.equals(str3); // 返回true,因为str1和str3引用的是同一个字符串常量(在内存中可能相同)

public boolean contentEquals(CharSequence cs)

  • 参数‌:cs - 要比较的字符序列。
  • 返回‌:如果当前字符串与指定的字符序列内容相同,则返回 true;否则返回 false。
  • 说明‌:这个方法会逐个字符地比较当前字符串和字符序列 cs 中的内容。如果它们包含相同数量的字符,并且每个字符在相应位置上都相同,则认为它们是内容相等的。

public boolean contentEquals(StringBuffer sb)

  • ‌参数‌:sb - 要比较的 StringBuffer 对象
  • ‌返回‌:如果当前字符串与 StringBuffer 对象中的内容相同,则返回 true;否则返回 false。
  • ‌说明‌:这个方法与上一个方法类似,但是它接受一个 StringBuffer 对象作为参数。StringBuffer 是一个可变的字符序列,这意味着它的内容可以在创建后更改。这个方法会逐个字符地比较当前字符串和 StringBuffer 中的内容,以确定它们是否相等。

在比较时,这两个方法都会考虑字符的大小写和顺序。如果参数为 null,则两个方法都会返回 false,因为 null 不被视为与任何字符串或字符序列内容相等。

public class StringContentEqualsExample {
    public static void main(String[] args) {
        String str = "Hello";
        
        // 使用 CharSequence 参数
        CharSequence cs = "Hello";
        boolean result1 = str.contentEquals(cs);
        System.out.println("Using CharSequence: " + result1); // 输出: true
        
        // 使用 StringBuffer 参数
        StringBuffer sb = new StringBuffer("Hello");
        boolean result2 = str.contentEquals(sb);
        System.out.println("Using StringBuffer: " + result2); // 输出: true
        
        // 比较不同内容
        cs = "World";
        boolean result3 = str.contentEquals(cs);
        System.out.println("Different content: " + result3); // 输出: false
    }
}

contentEquals 方法与 equals 方法不同。equals 方法用于比较两个对象是否是同一个对象的引用或是否是内容相等且类型也相同的字符串。而 contentEquals 方法只关心内容是否相等,不考虑对象的类型。

equals 方法:接受一个 Object 类型的参数,但在实际使用中,通常会传入一个 String 类型的对象进行比较。equals 方法的实现首先会检查两个对象是否是同一个实例(使用 == 运算符),然后比较它们的长度,最后逐个字符地比较内容。

contentEquals 方法:有两个重载版本,一个接受 CharSequence 类型的参数,另一个接受 StringBuffer 类型的参数。这使得 contentEquals 更加灵活,能够与不同类型的字符序列进行比较。contentEquals 方法直接逐个字符地比较当前字符串与传入的字符序列或 StringBuffer 对象的内容。对于 CharSequence 参数,它会调用该接口的 charAt 方法来获取字符进行比较;对于 StringBuffer 参数,它会调用 StringBuffer 的 charAt 方法。

public boolean regionMatches(int toffset, String other, int ooffset, int len)

这个方法用于比较两个字符串的指定区域,并且比较是区分大小写的。

‌参数‌:

  • toffset:此字符串中要比较的区域的起始索引(包括)。
  • other:要与此字符串进行比较的另一个字符串。
  • ooffset:other 字符串中要比较的区域的起始索引(包括)。
  • len:要比较的字符数。

‌返回值‌:如果两个字符串的指定区域相等(区分大小写),则返回 true。否则返回 false。

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

这个方法与上一个方法类似,但是它多了一个 ignoreCase 参数,用于指定比较时是否忽略大小写。

‌参数‌:

  • ignoreCase:如果为 true,则比较时忽略大小写;如果为 false,则比较时区分大小写。
  • toffset、other、ooffset、len:与上一个方法的参数含义相同。

‌返回值‌:

如果两个字符串的指定区域相等(根据 ignoreCase 参数决定是否区分大小写),则返回 true。否则返回 false。

String str1 = "HelloWorld";
String str2 = "helloworld";

// 使用regionMatches方法(区分大小写)
boolean isRegionMatchExact = str1.regionMatches(5, str2, 5, 5);
System.out.println("Is region match (exact): " + isRegionMatchExact); // 输出: false

// 使用regionMatches方法(忽略大小写)
boolean isRegionMatchIgnoreCase = str1.regionMatches(true, 5, str2, 5, 5);
System.out.println("Is region match (ignore case): " + isRegionMatchIgnoreCase); // 输出: true

8. 格式化:format

字符串格式化方法

public static String format(Locale l, String format, Object... args) {...} 
public static String format(String format, Object... args) {...}

在Java的String类中,format方法是一个静态方法,用于根据指定的格式字符串和参数创建一个格式化的字符串。String类提供了两个重载的format方法,它们允许你指定一个Locale(区域设置)或不指定,以便在格式化过程中考虑特定的文化和语言习惯。

以下是这两个方法的详细解释:

指定 Locale 的 format 方法

public static String format(Locale l, String format, Object... args)

‌参数‌:

  • l:一个 Locale 对象,表示要应用的格式的区域设置。区域设置影响数字、日期、时间等的格式。
  • format:一个格式字符串,它包含普通字符(这些字符将直接复制到结果字符串中)和格式说明符(这些说明符将被相应的参数替换)。
  • args:一个可变数量的参数,这些参数将被插入到格式字符串中的相应位置。

‌返回‌:一个格式化的字符串,其中格式说明符已被相应的参数替换。

不指定 Locale 的 format 方法

public static String format(String format, Object... args)

‌参数‌同上,返回‌一个格式化的字符串,与上面相同。不过,这个方法使用默认的区域设置(通常是系统区域设置)来进行格式化。

‌注意‌:如果不指定 Locale,则格式化行为可能会因运行 Java 应用程序的系统的区域设置而异。

格式说明符

格式说明符说明 示例
%s字符串类型"mingrisoft"
%c字符类型'm'
%b布尔类型true
%d整数类型(十进制)99
%x整数类型(十六进制)FF
%o整数类型(八进制)77
%f浮点类型99.99
%a十六进制浮点类型FF.35AE
%e指数类型9.38e+5
%g通用浮点类型(f 和 e 类型中较短的)
%h散列码
%%百分比类型
%n换行符
%tx日期与时间类型(x 代表不同的日期与时间转换符)
import java.util.Locale;

public class StringFormatExample {
    public static void main(String[] args) {
        // 使用默认区域设置格式化
        String formattedString = String.format("Hello, %s! You have %d new messages.", "Alice", 5);
        System.out.println(formattedString);//Hello, Alice! You have 5 new messages.

        // 使用特定区域设置格式化(例如,法国)
        Locale frenchLocale = Locale.FRANCE;
        String formattedStringWithLocale = String.format(frenchLocale, "Hello, %s! You have %d new messages.", "Alice", 5);
        System.out.println(formattedStringWithLocale);//Hello, Alice! You have 5 new messages.
    }
}

9. 转换:toLowerCase、toUpperCase

字符串转换方法

public String toLowerCase() {...} 
public String toLowerCase(Locale locale) {...} 
public String toUpperCase() {...} 
public String toUpperCase(Locale locale) {...}

public String toLowerCase()

将字符串中的所有字符转换为小写形式,使用默认的区域设置(通常是系统区域设置)。返回一个新的字符串,其中原始字符串中的所有大写字符都已转换为小写。如果字符串中没有大写字符,则返回原始字符串本身(或者一个等价的新字符串实例)。

public String toLowerCase(Locale locale)

将字符串中的所有字符转换为小写形式,使用指定的区域设置。locale 参数允许你指定一个特定的 Locale 对象,以便根据该区域的语言和文化习惯进行转换。返回一个新的字符串,其中根据指定区域设置,原始字符串中的所有大写字符都已转换为小写。

public String toUpperCase()

将字符串中的所有字符转换为大写形式,使用默认的区域设置。返回一个新的字符串,其中原始字符串中的所有小写字符都已转换为大写。如果字符串中没有小写字符,则返回原始字符串本身(或者一个等价的新字符串实例)。

public String toUpperCase(Locale locale)

将字符串中的所有字符转换为大写形式,使用指定的区域设置。locale 参数允许你指定一个特定的 Locale 对象,以便根据该区域的语言和文化习惯进行转换。返回一个新的字符串,其中根据指定区域设置,原始字符串中的所有小写字符都已转换为大写。

import java.util.Locale;

public class StringCaseConversionExample {
    public static void main(String[] args) {
        String str = "Hello, World!Ii";

        // 使用默认区域设置转换为小写
        String lowerCaseStr = str.toLowerCase();
        System.out.println(lowerCaseStr); //hello, world!ii

        // 使用特定区域设置(土耳其语)转换为小写
        // 注意:土耳其语中的'I'和'i'有特殊的转换规则
        Locale turkishLocale = new Locale("tr", "TR");
        String lowerCaseStrTurkish = str.toLowerCase(turkishLocale);
        System.out.println(lowerCaseStrTurkish); //hello, world!ıi

        // 使用默认区域设置转换为大写
        String upperCaseStr = str.toUpperCase();
        System.out.println(upperCaseStr); //HELLO, WORLD!II

        // 使用特定区域设置(例如,德语)转换为大写
        // 德语中没有特殊的大写转换规则,所以这里只是作为示例
        Locale germanLocale = Locale.GERMANY;
        String upperCaseStrGerman = str.toUpperCase(germanLocale);
        System.out.println(upperCaseStrGerman); //HELLO, WORLD!II
    }
}

10. 转换(数组):getBytes、toCharArray

也是字符串转换方法,不过是转换成字节或字符数组

public byte[] getBytes() {...} 
public byte[] getBytes(Charset charset) {...} 
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {...} 
public char[] toCharArray() {...}

public byte[] getBytes()‌

这个方法使用平台的默认字符集将此 String 编码为一系列字节,并将结果存储在一个新的字节数组中。平台的默认字符集是在 Java 虚拟机启动时确定的,并且通常依赖于底层操作系统和区域设置。返回一个包含此字符串的字节表示的新数组,使用平台的默认字符集进行编码。

public byte[] getBytes(Charset charset)‌

这个方法使用给定的 Charset 将此 String 编码为一系列字节,并将结果存储在一个新的字节数组中。这是一个更灵活的方法,因为它允许你明确指定用于编码的字符集。

‌参数‌:charset,用于编码此字符串的 Charset。

‌返回值‌:返回一个包含此字符串的字节表示的新数组,使用指定的 Charset 进行编码。

public byte[] getBytes(String charsetName) throws UnsupportedEncodingException‌

这个方法尝试使用指定的字符集名称将此 String 编码为一系列字节,并将结果存储在一个新的字节数组中。字符集名称是如 "UTF-8"、"ISO-8859-1" 等的字符串。

‌参数‌:charsetName,支持此字符串编码的字符集的名称。

‌抛出‌:UnsupportedEncodingException,如果指定的字符集不受支持。

‌返回值‌:返回一个包含此字符串的字节表示的新数组,使用指定的字符集进行编码。

String str = "Hello, World!";

// 使用平台默认字符集
byte[] bytesDefault = str.getBytes();

// 使用指定的Charset对象
Charset utf8 = StandardCharsets.UTF_8;
byte[] bytesUTF8 = str.getBytes(utf8);

// 使用指定的字符集名称
try {
    byte[] bytesISO = str.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}

在实际应用中,通常推荐使用 getBytes(Charset charset) 方法,因为它提供了更好的类型安全和可读性。如果你需要指定字符集名称,确保它是有效的并且你的环境支持它,否则可能会抛出 UnsupportedEncodingException。

public char[] toCharArray()

toCharArray 方法将字符串中的每个字符复制到一个新的字符数组中,并返回这个数组。这样,你就可以以数组的形式访问和操作字符串中的每个字符。该方法返回一个 char 类型的数组,该数组包含此字符串中的每个字符,顺序与字符串中的顺序相同。

String str = "我是中国人";
char[] charArray = str.toCharArray();

// 遍历字符数组
for (char c : charArray) {
    System.out.print(c + " ");
}
// 输出:我 是 中 国 人

toCharArray 方法在处理需要逐字符分析或修改字符串的场景时非常有用。例如,在实现自定义的字符串处理算法、密码学中的字符替换或加密解密等操作时,这个方法可以大大简化代码。

11. 转换(流):chars、lines

也是字符串转换方法,不过是转换成流

public IntStream chars() {...} 
public Stream<String> lines() {...}

在 String 类中,chars() 和 lines() 是两个用于生成流(Stream)的方法,但它们有不同的用途和返回类型。

public IntStream chars()

chars() 方法返回一个 IntStream,它是 Stream<Integer> 的一个特化版本,用于表示字符串中每个字符的 Unicode 码点(code point)序列。这个方法对于处理字符串中的字符非常有用,特别是当你需要对字符进行逐个处理,或者将字符转换为其他形式(如数字、字符数组等)时。

String str = "Hello";
IntStream charStream = str.chars();
charStream.forEach(ch -> System.out.println((char) ch));
// 输出:
// H
// e
// l
// l
// o

在这个示例中,chars() 方法生成了一个包含字符串 "Hello" 中每个字符 Unicode 码点的 IntStream。然后,我们使用 forEach 方法遍历这个流,并将每个码点转换回字符进行打印。

public Stream<String> lines()

lines() 方法返回一个Stream<String>,它将字符串按照行分隔符(通常是 \n,但也可以是其他系统相关的行分隔符)分割成多个子字符串,并将这些子字符串作为流中的元素。这个方法对于处理多行文本非常有用,特别是当你需要逐行处理文本时。

String multiLineString = "Line 1\nLine 2\nLine 3";
Stream<String> lineStream = multiLineString.lines();
lineStream.forEach(System.out::println);
// 输出:
// Line 1
// Line 2
// Line 3

在这个示例中,lines() 方法生成了一个包含字符串"Line 1\nLine 2\nLine 3"中每一行的Stream<String>。然后,我们使用 forEach 方法遍历这个流,并打印出每一行。

总结:

  • chars() 方法用于生成一个包含字符串中每个字符 Unicode 码点的 IntStream。
  • lines() 方法用于生成一个包含字符串按照行分隔符分割后每一行的Stream<String>

这两个方法都是 Java8 引入的流 API 的一部分,它们使得对字符串的处理更加灵活和强大。通过结合使用这些方法和流 API 的其他操作(如 filter、map、reduce 等),你可以轻松地实现复杂的字符串处理逻辑。

12. 拼接:concat、join、copyValueOf、repeat

字符串拼接方法

public String concat(String str) {...} 
public static String join(CharSequence delimiter, CharSequence... elements) {...} 
public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements) {...}
public static String copyValueOf(char data[]) {...} 
public static String copyValueOf(char data[], int offset, int count) {}
public String repeat(int count) {...} 

在 String 类中,concat 方法用于连接两个字符串,而 join 方法是静态的,用于将多个字符串或字符序列连接成一个单一的字符串,使用指定的分隔符。

concat 方法

public String concat(String str)

将指定的字符串参数 str 连接到当前字符串的末尾。返回一个新的字符串,该字符串是当前字符串和 str 参数连接后的结果。如果 str 为 null,则抛出 NullPointerException。

String str1 = "Hello";
String str2 = "World";
String result = str1.concat(str2);
System.out.println(result); // 输出: HelloWorld

join 方法

public static String join(CharSequence delimiter, CharSequence... elements)

使用指定的 delimiter(分隔符)将 elements(一个或多个字符序列)连接成一个单一的字符串。delimiter 是一个字符序列,它将被插入到 elements 的每个元素之间。elements 是一个可变参数,表示要连接的字符序列。如果 elements 为空或只包含一个元素,并且没有指定分隔符,则返回该元素本身(或空字符串)。如果 elements 包含 null 元素,则抛出 NullPointerException。

String delimiter = ", ";
String[] elements = {"Hello", "World", "Java"};
String result = String.join(delimiter, elements);
System.out.println(result); // 输出: Hello, World, Java

public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

与第一个 join 方法类似,但是这个版本接受一个 Iterable 的字符序列集合作为参数。delimiter 同样是一个字符序列,用作分隔符。elements 是一个实现了 Iterable 接口的对象,其元素类型为 CharSequence 或其子类型。这个方法会遍历 elements 集合,并使用 delimiter 将每个元素连接起来。如果 elements 为 null,则抛出 NullPointerException。如果集合为空,则返回空字符串。

String delimiter = "-";
List<String> elements = Arrays.asList("2023", "04", "01");
String result = String.join(delimiter, elements);
System.out.println(result); // 输出: 2023-04-01

copyValueOf 方法

String 类提供了两个重载的 copyValueOf 方法,用于将字符数组转换成字符串。

public static String copyValueOf(char data[])‌

这个方法接受一个字符数组 data 作为参数,并返回一个新的字符串,该字符串由数组中的所有字符组成。换句话说,它将整个字符数组转换成一个字符串。

‌参数说明‌:data,一个字符数组,包含要转换成字符串的所有字符。

‌返回值‌:返回一个包含 data 数组中所有字符的新字符串。

public static String copyValueOf(char data[], int offset, int count)‌

这个方法接受一个字符数组 data,以及两个整数 offset 和 count 作为参数。它返回一个新的字符串,该字符串由数组中从 offset 开始、长度为 count 的字符序列组成。这允许你只转换数组中的一部分为字符串。

‌参数说明‌:

  • data:一个字符数组,包含要转换成字符串的字符。
  • offset:开始的索引位置,从该位置开始复制字符(索引从零开始)。
  • count:要复制的字符数量。

‌返回值‌:返回一个包含从 data 数组的 offset 位置开始、长度为 count 的字符序列的新字符串。

char[] chars = {'H', 'e', 'l', 'l', 'o'};
String str = String.copyValueOf(chars);
System.out.println(str); // 输出:Hello

char[] chars1 = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
String str1 = String.copyValueOf(chars1, 6, 5);
System.out.println(str1); // 输出:World

这两个方法都是 String 类的静态方法,可以直接通过 String 类调用,不需要创建 String 对象。它们提供了一种方便的方式,用于将字符数组或数组的一部分转换成字符串。

repeat 方法

public String repeat(int count)

参数解释:count 表示原字符串需要重复的次数。如果 count 为 0,则返回一个空字符串。如果 count 为负数,则会抛出 StringIndexOutOfBoundsException 异常。

返回值:返回一个新字符串,它是原字符串重复 count 次后拼接而成的。

使用 repeat 方法时,需要注意以下几点:

  • 重复次数:count 必须是一个非负整数。如果 count 为负数,程序会抛出 StringIndexOutOfBoundsException 异常。
  • 性能考虑:对于大字符串和大量的重复次数,这个方法可能会消耗较多的内存和时间。因此,在使用时需要注意性能问题。
String original = "abc";
String repeated = original.repeat(3);
System.out.println(repeated); // 输出 "abcabcabc"

13. 判断:isBlank、isEmpty

字符串判断方法

public boolean isEmpty() {...}
public boolean isBlank() {...} 

在 Java 的标准库中,String 类并没有直接提供 isBlank() 方法,直到 Java 11 版本,String 类才引入了这个方法。而 isEmpty() 方法则是从 Java 1.6 版本开始就已经存在了。这两个方法都是用来判断字符串是否为空或者为空白字符串,但是它们有细微的差别。

public boolean isEmpty()

‌功能‌:判断字符串是否为空字符串。

‌返回值‌:如果字符串的长度为 0,即字符串没有任何字符,则返回 true;否则返回 false。

public boolean isBlank()

‌功能‌:判断字符串是否为空白字符串。

‌返回值‌:如果字符串为空或者只包含空白字符(如空格、制表符、换行符等),则返回true;否则返回false。

String str1 = "";
String str2 = " ";
String str3 = "\t";
String str4 = "Hello";
System.out.println(str1.isBlank()); // 输出: true
System.out.println(str1.isEmpty()); // 输出: true
System.out.println(str2.isBlank()); // 输出: true
System.out.println(str2.isEmpty()); // 输出: false
System.out.println(str3.isBlank()); // 输出: true
System.out.println(str3.isEmpty()); // 输出: false
System.out.println(str4.isBlank()); // 输出: false
System.out.println(str4.isEmpty()); // 输出: false

如果你在使用 Java 11 之前的版本,并且需要类似 isBlank() 的功能,你可以自己实现一个方法,或者使用第三方库(如 Apache Commons Lang 的 StringUtils.isBlank())。 在处理用户输入或外部数据时,使用 isBlank() 通常比 isEmpty() 更加安全,因为它能够检测到只包含空白字符的字符串,这些字符串在很多情况下应该被视为无效或空值。

14. 信息:length、hashCode

字符串信息方法

public int length() {...} 
public int hashCode() {...}

public int length()

‌功能‌:返回字符串的长度,即字符串中字符的个数。

‌返回值‌:一个 int 类型的值,表示字符串中字符的数量。

‌注意‌:这里的长度是指字符的数量,而不是字节的数量。对于包含多字节字符(如中文字符)的字符串,长度仍然按照字符来计算。

String str = "Hello, World!";
int length = str.length();
System.out.println("Length of the string: " + length); // 输出: Length of the string: 13

public int hashCode()

‌功能‌:返回字符串的哈希码。哈希码是一个整数,它用于在哈希表等数据结构中快速定位对象。

‌返回值‌:一个 int 类型的值,表示字符串的哈希码。

‌实现‌:String 类的 hashCode() 方法通常基于字符串的内容来计算哈希码,确保内容相同的字符串具有相同的哈希码。具体的实现算法可能会因 Java 版本的不同而有所差异,但通常都涉及到字符串内部字符的某种数学运算。

‌注意‌:哈希码并不是唯一的,即不同的字符串可能会有相同的哈希码(哈希碰撞),但在大多数情况下,哈希码能够有效地分散字符串在哈希表中的位置。

String str1 = "Hello";
String str2 = "World";
int hashCode1 = str1.hashCode();
int hashCode2 = str2.hashCode();
System.out.println("Hash code of 'Hello': " + hashCode1);
System.out.println("Hash code of 'World': " + hashCode2);

length() 方法的时间复杂度是 O(1),因为它只是简单地返回字符串内部存储的长度值。

hashCode() 方法的时间复杂度通常是 O(n),其中 n 是字符串的长度,因为它需要遍历字符串的每个字符来计算哈希码。不过,由于哈希码的计算是高效的,并且在实际应用中,字符串的哈希码通常会被缓存以提高性能,所以这个方法在实际使用中通常是很快的。

在使用哈希表(如 HashMap、HashSet 等)时,hashCode() 方法非常重要,因为它决定了对象在哈希表中的位置。如果两个对象被认为是相等的(即 equals() 方法返回 true),那么它们的哈希码也必须相等。这是哈希表正确工作的基本要求之一。

15. 码点:codePoints、codePointAt、codePointBefore、codePointCount、offsetByCodePoints

与 Unicode 代码点(code points)相关的方法

public IntStream codePoints() {...}
public int codePointAt(int index) {...} 
public int codePointBefore(int index) {...} 
public int codePointCount(int beginIndex, int endIndex) {...}
public int offsetByCodePoints(int index, int codePointOffset) {...} 

String 类提供了与 Unicode 代码点(code points)相关的一系列方法,这些方法允许你更深入地操作和查询字符串中的字符。Unicode 代码点是分配给 Unicode 字符的唯一数字标识,它们可以表示世界上几乎所有的书写系统中的字符。在 Java 的字符串处理中,理解这些方法对于正确处理多字节字符(如表情符号和一些特殊字符)至关重要。

public IntStream codePoints()‌

这个方法返回一个 IntStream,其中包含此字符串中每个字符的 Unicode 代码点。IntStream 是 Java 8 引入的流 API 的一部分,它允许你以声明性的方式处理元素序列。这个方法对于遍历字符串中的所有字符(包括那些由多个 Java char 组成的字符)非常有用。

public int codePointAt(int index)‌

返回指定索引处的字符的 Unicode 代码点。索引指的是 char 值(而不是代码点)的索引。如果索引处的字符是一个代理项对(即,两个 char 组成一个 Unicode 代码点),则此方法会返回该代理项对表示的代码点。

public int codePointBefore(int index)‌

返回紧接在指定索引之前的字符的 Unicode 代码点。这个方法在处理字符串时非常有用,特别是当你需要获取某个字符之前的字符的代码点时。如果索引是 0,或者索引之前的字符是一个代理项对的第一个 char,则此方法会抛出 StringIndexOutOfBoundsException。

public int codePointCount(int beginIndex, int endIndex)‌

返回此字符串从 beginIndex(包含)到 endIndex(不包含)之间的 Unicode 代码点的数量。这个方法对于计算子字符串中的字符数量(考虑到多字节字符)非常有用。

public int offsetByCodePoints(int index, int codePointOffset)‌

根据指定的代码点偏移量,从给定的索引开始计算新的索引。这个方法允许你在字符串中根据代码点而不是 char 值进行索引移动。这对于处理包含多字节字符的字符串特别有用,因为你可以直接根据代码点数量来移动索引,而不是担心代理项对的问题。

以下是一些使用这些方法的示例:

String str = "Hello, 🌍!";

// 使用 codePoints 方法遍历所有代码点
str.codePoints().forEach(codePoint -> System.out.println("Code Point: " + codePoint));
/*
Code Point: 72
Code Point: 101
Code Point: 108
Code Point: 108
Code Point: 111
Code Point: 44
Code Point: 32
Code Point: 127757
Code Point: 33
*/

// 获取索引为4的字符的代码点('o')
int codePointAtIndex4 = str.codePointAt(4);
System.out.println("Code Point at index 4: " + codePointAtIndex4);//Code Point at index 4: 111

// 获取索引为4之前的字符的代码点('H')
int codePointBeforeIndex4 = str.codePointBefore(4);
System.out.println("Code Point before index 4: " + codePointBeforeIndex4);//Code Point before index 4: 108

// 计算从索引0到索引7之间的代码点数量(包括'🌍'这个多字节字符)
int codePointCount = str.codePointCount(0, 7);
System.out.println("Code Point count from index 0 to 7: " + codePointCount);//Code Point count from index 0 to 7: 7

// 从索引4开始,向后移动2个代码点的位置
int newIndex = str.offsetByCodePoints(4, 2);
System.out.println("New index after moving 2 code points from index 4: " + newIndex);//New index after moving 2 code points from index 4: 6

这些方法为处理 Unicode 字符串提供了强大的工具,特别是当字符串包含多字节字符时。通过正确地使用这些方法,你可以确保在处理字符串时不会丢失或错误地解释字符。

16. 匹配:matches

字符串匹配方法

public boolean matches(String regex) {...}

这个方法用于判断字符串是否匹配给定的正则表达式。它接受一个字符串参数 regex,该参数表示要匹配的正则表达式。如果字符串与正则表达式匹配,则返回 true;否则返回 false。

String str = "Hello, World!"; 

// 使用matches方法匹配正则表达式 
boolean isMatch = str.matches("Hello.*"); 
System.out.println("Is match: " + isMatch); // 输出: Is match: true

17. 其他:intern、toString

其他方法

public native String intern(); 
public String toString() {...}

public native String intern();

intern() 方法是 String 类中的一个本地(native)方法,它的作用是返回字符串对象的“规范化”表示,确保相同的字符串字面量在 Java 虚拟机(JVM)的内存中只存在一份。这个方法对于性能优化和内存管理非常重要,特别是在需要大量字符串比较的场景中。

当你创建一个字符串对象时,JVM 会在堆内存中为这个对象分配空间,并存储字符串的内容。如果你再次创建一个内容相同的字符串对象,JVM 通常会再次分配空间来存储这个新对象的内容,即使这两个字符串的内容是完全相同的。这样,内存中就会存在多个表示相同字符串的对象,这既浪费了内存空间,又增加了字符串比较时的复杂性。

intern() 方法通过查找字符串常量池(一个特殊的内存区域,用于存储所有被 intern 过的字符串)来避免这种情况。当你调用一个字符串对象的 intern() 方法时,JVM 会检查字符串常量池中是否已经存在一个内容相同的字符串对象:

如果存在,JVM 会返回常量池中的那个字符串对象的引用,而不是创建一个新的对象。 如果不存在,JVM 会将此字符串对象添加到常量池中,并返回此对象的引用。

这样,通过 intern() 方法,你可以确保所有内容相同的字符串对象在内存中只存在一份,从而节省内存空间并提高字符串比较的效率。

需要注意的是,intern() 方法是一个本地方法,它的实现依赖于 JVM 的具体实现。因此,不同的 JVM 可能会对 intern() 方法有不同的优化策略。此外,由于 intern() 方法涉及到字符串常量池的操作,所以在某些情况下(特别是当字符串非常多且内存有限时),使用 intern() 方法可能会导致性能下降或内存溢出。因此,在使用 intern() 方法时,需要根据具体的应用场景进行权衡和测试。

public String toString() {...}

toString() 方法是 Object 类中的一个实例方法,也是 Java 中所有类都会继承的一个方法(因为每个类都直接或间接继承自 Object 类)。toString() 方法的主要作用是返回对象的字符串表示形式,这通常用于调试、日志记录或将对象转换为字符串以进行显示或存储。

对于 String 类本身来说,toString() 方法的实现非常简单且直接,因为它本身就是表示字符串的类。String 类的 toString() 方法只是返回调用它的那个字符串对象本身。

对于其他类来说,toString() 方法通常会被重写以提供更有意义的字符串表示。例如,一个表示人的类可能会重写 toString() 方法来返回人的姓名、年龄等信息。如果类没有重写 toString() 方法,那么调用这个方法将返回类名、符号 "@" 以及对象的哈希码的无符号十六进制表示,这通常不是很有用。