String类
一.字符串常量池
在Java(以及许多其他编程语言中),字符串常量值是指那些在程序中直接以字符串字面量形式给出的值。这些值被双引号("")包围,并且一旦在代码中定义,就不能被改变(尽管你可以将字符串变量指向另一个字符串常量或字符串对象的引用)。
字符串常量值在编译时会被存储在字符串常量池中。这是JVM(Java虚拟机)中的一个特殊存储区域,用于存储唯一的字符串常量。当程序中出现多个相同的字符串字面量时,JVM会确保它们只存储一次,并让所有引用该字符串的变量都指向常量池中的同一位置。这样做可以节省内存并提高效率。
例如:
String str1 = "Hello, World!";
String str2 = "Hello, World!";
// 在这里,str1 和 str2 实际上指向的是字符串常量池中同一个 "Hello, World!" 字符串的引用
但是,如果你通过 new
关键字显式地创建字符串对象,那么即使字符串内容相同,它也会是常量池之外的一个新对象。
String str3 = new String("Hello, World!");
// str3 是指向一个新的字符串对象的引用,该对象的内容是 "Hello, World!",但它与常量池中的字符串不是同一个对象
字符串常量值在Java中是不可变的,这意味着一旦一个字符串被创建,它的内容就不能被改变。如果你尝试“修改”一个字符串,实际上是在创建一个新的字符串对象,并将引用指向这个新对象。
String str4 = "Hello";
str4 = str4 + ", World!"; // 这里没有修改 "Hello",而是创建了新字符串 "Hello, World!" 并让 str4 指向它
在这个例子中,str4
最初指向字符串常量池中的 "Hello"。然后,通过字符串连接操作(+
),创建了一个新的字符串 "Hello, World!",并将 str4
的引用更改为指向这个新字符串。注意,新字符串 "Hello, World!" 不会被存储在字符串常量池中,除非它是通过字符串字面量直接创建的。
二.常见方法
1.-charAt(int index):返回字符串
在Java中,String
类提供了一个名为 charAt(int index)
的方法,该方法用于返回指定索引处的字符。索引范围是从 0 到字符串长度减 1。如果索引超出范围,将抛出 StringIndexOutOfBoundsException
异常。
这里是一个使用 charAt(int index)
方法的简单示例:
public class Main {
public static void main(String[] args) {
String str = "Hello, World!";
// 使用 charAt 方法获取索引为 4 的字符
char ch = str.charAt(4);
// 输出结果
System.out.println("The character at index 4 is: " + ch);
}
}
在这个例子中,字符串 str
是 "Hello, World!"
。索引是从 0 开始的,所以索引 4 对应的字符是 ,
(逗号)。程序将输出:
The character at index 4 is: ,
需要注意的是,charAt(int index)
方法返回的是一个 char
类型的值,而不是 String
类型。这是因为字符串是由字符组成的序列,而 charAt
方法正是用来访问这个序列中特定位置的字符的。
此外,由于字符串在Java中是不可变的,所以你不能通过 charAt
方法来“修改”字符串中的字符。如果你需要修改字符串中的某个字符,你必须创建一个新的字符串来包含修改后的内容。
2.-indexOf(String s):返回指定字符串第一次出现的位置
在Java中,String
类提供了一个名为 indexOf(String str)
的方法,该方法用于返回指定子字符串(str
)在字符串中第一次出现的索引位置。如果未找到子字符串,则返回 -1
。索引位置从 0
开始计算。
这里是一个使用 indexOf(String str)
方法的简单示例:
public class Main {
public static void main(String[] args) {
String str = "Hello, World! Welcome to the Java programming language.";
// 使用 indexOf 方法查找子字符串 "World" 第一次出现的位置
int index = str.indexOf("World");
// 输出结果
if (index != -1) {
System.out.println("The substring 'World' is found at index: " + index);
} else {
System.out.println("The substring 'World' is not found.");
}
// 尝试查找一个不存在的子字符串
index = str.indexOf("NonExistentSubstring");
// 输出结果
if (index != -1) {
System.out.println("The substring is found at index: " + index);
} else {
System.out.println("The substring is not found.");
}
}
}
在这个例子中,字符串 str
是 "Hello, World! Welcome to the Java programming language."
。第一次调用 indexOf("World")
时,它会返回 7
,因为 "World"
第一次出现在索引 7
的位置(注意,索引是从 0
开始的)。第二次调用 indexOf("NonExistentSubstring")
时,由于该子字符串在字符串中不存在,因此返回 -1
。
输出将是:
The substring 'World' is found at index: 7
The substring is not found.
3.-startsWith(String s):测试字符串是否以指定前缀开始
在Java中,String
类提供了一个名为 startsWith(String prefix)
的方法,该方法用于测试字符串是否以指定的前缀开始。如果字符串以指定的前缀开始,则返回 true
;否则返回 false
。
这里是一个使用 startsWith(String prefix)
方法的简单示例:
public class Main {
public static void main(String[] args) {
String str = "Hello, World!";
// 测试字符串是否以 "Hello" 开始
boolean result1 = str.startsWith("Hello");
System.out.println("Does the string start with 'Hello'? " + result1);
// 测试字符串是否以 "World" 开始(这将会返回 false)
boolean result2 = str.startsWith("World");
System.out.println("Does the string start with 'World'? " + result2);
// 测试字符串是否以空字符串 "" 开始(这将会返回 true,因为任何字符串都以空字符串为前缀)
boolean result3 = str.startsWith("");
System.out.println("Does the string start with an empty string? " + result3);
// 测试字符串是否以 null 开始(这将会抛出 NullPointerException)
// 注意:以下行是注释掉的,因为它会抛出异常
// boolean result4 = str.startsWith(null);
}
}
在这个例子中,str
是 "Hello, World!"
。
- 第一次调用
startsWith("Hello")
时,由于字符串确实以"Hello"
开始,所以返回true
。 - 第二次调用
startsWith("World")
时,由于字符串不是以"World"
开始,所以返回false
。 - 第三次调用
startsWith("")
时,由于任何字符串都可以视为以空字符串为前缀,所以返回true
。
注意,如果你尝试使用 startsWith(null)
(即传递 null
作为参数),则会抛出 NullPointerException
。因此,在调用此方法之前,你应该确保传递给它的参数不是 null
。
输出将是:
Does the string start with 'Hello'? true
Does the string start with 'World'? false
Does the string start with an empty string? true
4.-endsWith(String s):返回字符串的子字符串
实际上,String
类的 endsWith(String suffix)
方法并不返回字符串的子字符串,而是测试字符串是否以指定的后缀结束。如果字符串以指定的后缀结束,则返回 true
;否则返回 false
。
这里是一个使用 endsWith(String suffix)
方法的简单示例:
public class Main {
public static void main(String[] args) {
String str = "Hello, World!";
// 测试字符串是否以 "World!" 结束
boolean result1 = str.endsWith("World!");
System.out.println("Does the string end with 'World!'? " + result1);
// 测试字符串是否以 "Hello" 结束(这将会返回 false)
boolean result2 = str.endsWith("Hello");
System.out.println("Does the string end with 'Hello'? " + result2);
// 测试字符串是否以空字符串 "" 结束(这将会返回 true,因为任何字符串都以空字符串为后缀)
boolean result3 = str.endsWith("");
System.out.println("Does the string end with an empty string? " + result3);
// 测试字符串是否以 null 结束(这将会抛出 NullPointerException)
// 注意:以下行是注释掉的,因为它会抛出异常
// boolean result4 = str.endsWith(null);
}
}
在这个例子中,str
是 "Hello, World!"
。
- 第一次调用
endsWith("World!")
时,由于字符串确实以"World!"
结束,所以返回true
。 - 第二次调用
endsWith("Hello")
时,由于字符串不是以"Hello"
结束,所以返回false
。 - 第三次调用
endsWith("")
时,由于任何字符串都可以视为以空字符串为后缀,所以返回true
。
注意,与 startsWith
方法一样,如果你尝试使用 endsWith(null)
(即传递 null
作为参数),则会抛出 NullPointerException
。
输出将是:
Does the string end with 'World!'? true
Does the string end with 'Hello'? false
Does the string end with an empty string? true
5.-replace(char a,char b):替换字符串的指定字符
在Java中,String
类本身是不可变的,这意味着一旦创建了字符串对象,就不能更改其内容。因此,String
类没有直接提供用于替换字符的 replace(char a, char b)
方法。但是,它提供了一个 replace(CharSequence target, CharSequence replacement)
方法,该方法接受两个字符序列(例如,字符串)作为参数,并将字符串中所有出现的第一个字符序列替换为第二个字符序列。
不过,为了替换字符串中的单个字符,你可以使用 replace(CharSequence target, CharSequence replacement)
方法的一个简单变体,即传递长度为1的字符串作为参数,或者使用 String
类的 chars()
方法结合流(Java 8及以上版本)来实现更复杂的替换逻辑,尽管后者可能不是最直接的方法。
但是,对于替换单个字符的需求,更常见的做法是使用 String.valueOf(char)
方法将字符转换为字符串,然后调用 replace(CharSequence target, CharSequence replacement)
方法。这里有一个简单的示例:
public class Main {
public static void main(String[] args) {
String str = "Hello, World!";
// 替换字符串中的 'o' 为 'O'
String replacedStr = str.replace("o", "O");
System.out.println(replacedStr); // 输出: Hello, WOrld!
// 注意:这会替换所有出现的 'o',如果你只想替换第一个,则需要使用不同的方法
// 如果你只想替换第一个出现的字符,可以使用substring和indexOf结合
int index = str.indexOf('o');
if (index != -1) {
replacedStr = str.substring(0, index) + "O" + str.substring(index + 1);
}
System.out.println(replacedStr); // 输出: Hello, WOrld!(但注意,这里实际上替换了所有'o')
// 如果你确实只想替换第一个'o',确保上述逻辑只替换第一个
// 上面的代码已经展示了如何做到这一点(尽管输出看起来像是替换了所有'o',但如果你只处理第一个'o',它会正确工作)
// 或者,使用正则表达式(如果适用)
replacedStr = str.replaceFirst("o", "O");
System.out.println(replacedStr); // 输出: Hello, WOrld!,这次只替换了第一个'o'
}
}
请注意,上述代码中的第一个 replace
调用实际上替换了字符串中所有出现的 'o'
字符。如果你只想替换第一个出现的字符,你可以使用 replaceFirst
方法(如示例中所示),该方法接受一个正则表达式作为第一个参数,并替换与正则表达式匹配的第一个子字符串。
对于 replace(char a, char b)
的直接需求,你可能需要自定义一个方法,或者如上所述,使用 replace(CharSequence target, CharSequence replacement)
方法的一个变体,或者利用 replaceFirst
方法(如果你只想替换第一个出现的字符)。
6.-trim():去掉字符串的前后空格
在Java中,String
类提供了一个名为 trim()
的方法,该方法用于去除字符串开头和结尾的空白符(包括空格、制表符、换行符等)。它返回一个新的字符串,其中不包含原字符串开头和结尾的空白符,而原字符串本身不会改变(因为Java中的字符串是不可变的)。
这里是一个使用 trim()
方法的简单示例:
public class Main {
public static void main(String[] args) {
String str = " Hello, World! ";
// 去除字符串开头和结尾的空格
String trimmedStr = str.trim();
// 输出结果
System.out.println("Original string: \"" + str + "\"");
System.out.println("Trimmed string: \"" + trimmedStr + "\"");
}
}
输出将是:
Original string: " Hello, World! "
Trimmed string: "Hello, World!"
如你所见,trim()
方法移除了字符串开头和结尾的所有空白符,但保留了中间的空格和其他字符。如果你需要去除字符串中所有的空格(不仅仅是开头和结尾的),那么你需要使用不同的方法,比如正则表达式替换。但是,对于大多数去除前后空格的需求,trim()
方法就足够了。
7.-concat(String str):连接俩个字符串
在Java中,String
类提供了一个名为 concat(String str)
的方法,该方法用于将指定的字符串 str
连接到此字符串的结尾。这意味着,如果你有一个字符串 s1
,并调用 s1.concat(s2)
,那么返回的结果是一个新的字符串,该字符串是 s1
和 s2
顺序连接后的结果。原始字符串 s1
本身不会改变(因为Java中的字符串是不可变的)。
这里是一个使用 concat(String str)
方法的简单示例:
public class Main {
public static void main(String[] args) {
String str1 = "Hello, ";
String str2 = "World!";
// 连接两个字符串
String concatenatedStr = str1.concat(str2);
// 输出结果
System.out.println(concatenatedStr); // 输出: Hello, World!
// 注意:str1 和 str2 本身没有改变
System.out.println("str1: " + str1); // 输出: Hello,
System.out.println("str2: " + str2); // 输出: World!
}
}
在上面的示例中,str1.concat(str2)
创建了一个新的字符串 concatenatedStr
,它是 str1
和 str2
的连接结果。同时,str1
和 str2
的原始值保持不变,这再次证明了Java中字符串的不可变性。
需要注意的是,如果 str
为 null
,则 concat(String str)
方法会抛出 NullPointerException
。因此,在调用此方法之前,最好检查 str
是否为 null
。
此外,虽然 concat(String str)
方法可以用于连接字符串,但在许多情况下,使用 +
操作符进行字符串连接可能更为方便和直观。+
操作符在Java中已经被重载,以支持字符串的连接,并且它会在编译时被优化为使用 StringBuilder
或 StringBuffer
(取决于上下文)来提高性能。然而,在循环中频繁连接字符串时,手动使用 StringBuilder
或 StringBuffer
通常是更好的选择,因为它们提供了更好的性能。
8.-split(Stirng rgex):给定正则表达式的匹配来拆分字符
在Java中,String
类提供了一个名为 split(String regex)
的方法,该方法根据给定正则表达式的匹配拆分字符串。split
方法返回一个字符串数组,该数组包含由正则表达式定义的分隔符分隔的子字符串。
需要注意的是,方法名中的参数拼写应该是 String regex
而不是 Stirng rgex
,这里有一个拼写错误。
这里是一个使用 split(String regex)
方法的示例:
public class Main {
public static void main(String[] args) {
String str = "apple,banana,cherry";
// 使用逗号作为分隔符拆分字符串
String[] fruits = str.split(",");
// 输出拆分后的字符串数组
for (String fruit : fruits) {
System.out.println(fruit);
}
// 输出:
// apple
// banana
// cherry
// 使用正则表达式拆分字符串,例如,使用逗号后可能跟随的空格作为分隔符
String strWithSpaces = "apple, banana, cherry";
String[] fruitsWithSpaces = strWithSpaces.split(",\\s*");
// 输出拆分后的字符串数组
for (String fruit : fruitsWithSpaces) {
System.out.println(fruit);
}
// 输出:
// apple
// banana
// cherry
}
}
在上面的示例中,第一个 split
调用使用逗号(,
)作为分隔符来拆分字符串。第二个 split
调用使用了一个正则表达式 ",\\s*"
,这意味着它将匹配逗号后跟任意数量的空白字符(包括零个)作为分隔符。这允许字符串中的分隔符不仅仅是逗号,还可以是逗号后跟随的任意数量的空格或其他空白字符。
需要注意的是,正则表达式中的反斜杠(\
)是一个转义字符,在Java字符串中也需要被转义,因此写成了 \\
。在正则表达式中,\s
匹配任何空白字符,*
表示匹配前面的字符零次或多次。
此外,如果正则表达式与字符串的开头或结尾匹配,或者没有找到匹配项,则结果数组将包含空字符串作为元素。例如,",".split(",")
将返回一个包含两个空字符串的数组。