【Java常用类】1-3 String 类
§1-3 String
类
- §1-3
String
类- 1-3.1
String
概述 - 1-3.2 常用方法
- 1-3.2.1
equals(Object obj);
,equalsIgnoreCase(String str);
- 1-3.2.2
compareTo(String str);
,compareToIgnoreCase(String str);
- 1-3.2.3
length();
- 1-3.2.4
isEmpty();
,isBlank();
- 1-3.2.5
charAt(int index);
- 1-3.2.6
codePointAt(int index);
- 1-3.2.7
contains(String str);
- 1-3.2.8
toCharArray();
- 1-3.2.9
trim();
- 1-3.2.10
indexOf();
,lastIndexOf();
- 1-3.2.11
startsWith();
,endsWith(String suffix);
- 1-3.2.12
toLowerCase();
,toUpperCase();
- 1-3.2.13
replace();
,replaceAll();
- 1-3.2.14
split(String regex);
- 1-3.2.15
concat();
- 1-3.2.16
substring();
- 1-3.2.1
- 1-3.3 案例演示
- 1-3.1
1-3.1 String
概述
在基础课,我们早已接触 String
类。String
类并不属于八大基本类型之一,而属于类。
首先来看看 String
类的一些特点:
- 字符串的字面值存储在字符串池中,可以共享;
- 字符串是常量,创建之后不可改变;
- 使用赋值方式创建
String
对象时,字符串会在字符串池中存储; - 使用
new
语句创建String
对象时,会产生两个对象:堆、字符串池中各存储一个。使用这种方式创建对象较浪费空间; - 根据 JDK 版本的不同,字符串池可能在堆中,也可能在方法区中,因版本而异。
String
适合用于操作量较少时的情况。
解释:
使用赋值语句创建字符串:
String str1 = "Hello";
str1 = "world";
String str2 = str1;
运行时,首先会在字符串池中查找是否存在该字符串。若没有,则在池中创建该字符串,并让引用指向该地址。
然后,str1
的值 “发生改变”,实际上,池中创建了一个新的字符串,内容是 world
,并让栈中的引用 str1
指向池中的 world
。此时,Hello
被废弃,若无更多引用,触发垃圾回收器则可能会触发回收。
从这一点上看,字符串是常量,创建后不可改变。看似改变其值的语句,实际上是在更改引用的指向。
str2 = str1
,二者共同指向池中相同的字符串。使用 ==
运算符可比较引用指向地址是否相同:
System.out.println(str1 == str2);
得到:
true
二者共同指向池中的 Hello
。
使用 new
创建字符串:
String str3 = new String("Java");
String str4 = new String("Java");
使用 new
语句,则仅会在池中创建对象,堆中也会创建对象,存储内容都是池中共同且唯一的 "Java"
。此时,栈中的引用变量分别指向堆中不同的对象,但堆中不同的对象所存储内容实际上都来自池中相同的字符串。使用 ==
运算符,可用于比较引用的地址是否相同:
System.out.println(str3 == str4);
得到:
false
二者分别指向堆中的不同对象。
由此可见,比较字符串内容时,通常使用 equals()
方法。由于 String
类重写了 Object
类的 equals()
方法,使得这一操作变为可行。
1-3.2 常用方法
String
类中的一些常用方法如下:
1-3.2.1 equals(Object obj);
,equalsIgnoreCase(String str);
equals(Obj obj);
:将此字符串与指定对象进行比较。此处不再赘述。
equalsIgnoreCase(String str)
:将此字符串与另一个字符串作比较,忽略大小写。
1-3.2.2 compareTo(String str);
,compareToIgnoreCase(String str);
compareTo(String str);
:按字典顺序比较两个字符串。
compareToIgnoreCase(String str);
:按字典顺序比较两个字符串,忽略大小写。
示例:该方法比较的是第一个出现差异的字符的编码,返回二者编码之差。
String str1 = "abc"; //a -> 97
String str2 = "xyz"; //x ->120
String str3 = "abcxyz";
System.out.println(str1.compareTo(str2)); //97 - 120 = -23
System.out.println(str9.compareTo(str11)); //长度不等,但前面相同,比较长度
得到
-23
-3
1-3.2.3 length();
描述:返回此字符串的长度。
示例:
String str = "Hello";
System.out.println(str.length());
得到
5
1-3.2.4 isEmpty();
,isBlank();
isEmpty();
:判断字符串是否为空,当且仅当 length() == 0
时返回 true
。
isBlank();
:判断字符串是否仅含有空白字符,当字符串为空或仅含有空白字符时返回 true
。
示例:
String str;
str = "";
System.out.println("str.isEmpty() = " + str.isEmpty());
System.out.println("str.isBlank() = " + str.isBlank());
str = "\r\n";
System.out.println("str.isEmpty() = " + str.isEmpty());
System.out.println("str.isBlank() = " + str.isBlank());
str = "Hello";
System.out.println("str.isEmpty() = " + str.isEmpty());
System.out.println("str.isBlank() = " + str.isBlank());
得到
str5.isEmpty() = true
str5.isBlank() = true
str5.isEmpty() = false
str5.isBlank() = true
str5.isEmpty() = false
str5.isBlank() = false
1-3.2.5 charAt(int index);
描述:返回指定索引(下标)处的字符。
示例:
String str = "Hello";
System.out.println(str.charAt(1));
System.out.println(str.charAt(str.length() - 1));
得到:
e
o
注意:下标越界会抛出异常 StringIndexOutOfBoundsException
,其父类是 IndexOutOfBoundsException
,均属于运行时异常(RuntimeException
)。
1-3.2.6 codePointAt(int index);
描述:返回指定索引处的字符(Unicode 代码点)
示例:
String str = "你好世界!";
System.out.println("索引 0 处的 Unicode 代码点:" + str2.codePointAt(0));
得到:
索引 0 处的 Unicode 代码点:20320
什么是代码点?
Unicode 字符集中,每一个字符对应一个 codepoint,即代码点。Java 的 char
占用 2 字节,总共只能表示 \(2^{16} = 65536\) 种字符,远少于 Unicode 中的字符数。这时候需要两个 char
才能表示一个 Unicode 字符了,此时,codepoint 就是对应两个 char
所表示的一个字符。
1-3.2.7 contains(String str);
描述:判断当前字符串中是否包含 str
。
示例:
String str = "Java is the best programming language.";
System.out.println(str.contains("php"));
得到:
false
1-3.2.8 toCharArray();
描述:将字符串转换为新的字符数组。
示例:
String str = "Hello world!";
char[] chs = str.toCharArray();
System.out.println("字符数组 str: " + Arrays.toString(chs));
得到:
字符数组 str: [H, e, l, l, o, , w, o, r, l, d, !]
1-3.2.9 trim();
描述:删除字符串前后的空格,其中空格定义为代码点小于或等于 'U+0020'
(空格字符)的任何字符。
示例:
String str = " 博客园 ";
System.out.println("原始字符串:" + str);
System.out.println("处理后字符串:" + str.trim());
得到:
原始字符串: 博客园
处理后字符串:博客园
1-3.2.10 indexOf();
,lastIndexOf();
indexOf(String str);
:返回指定子字符串在该字符串中第一次出现的索引。
lastIndexOf(String str);
:返回最后一次出现的指定子字符串在此字符串中的索引。
示例:
String str = "Hello world!";
//找不到则返回 -1
System.out.println("str 中首次出现 l 的索引:" + str.indexOf("l"));
System.out.println("str 中最后出现 l 的索引:" + str.lastIndexOf("l"));
System.out.println("str 中首次出现 z 的索引:" + str.indexOf('z'));
System.out.println(sep);
得到:
str 中首次出现 l 的索引:2
str 中最后出现 l 的索引:9
str 中首次出现 z 的索引:-1
该方法的其他重载:
方法 | 行为 |
---|---|
public int indexOf(String str); |
返回指定子字符串在该字符串中第一次出现的索引 |
public int indexOf(String str, int fromIndex); |
从指定索引开始,返回第一次出现的指定子字符串在此字符串中的索引 |
public int indexOf(int ch); |
返回指定字符在此字符串中第一次出现的索引 |
public int indexOf(int ch, int fromIndex); |
返回指定字符在此字符串中第一次出现的索引,从指定索引处开始搜索 |
public int lastIndexOf(String str); |
返回最后一次出现的指定子字符串在此字符串中的索引 |
public int lastIndexOf(String str, int fromIndex); |
返回最后一次出现的指定子字符串在此字符串中的索引,从指定索引开始向后搜索 |
public int lastIndexOf(int ch); |
返回最后一次出现的指定字符在此字符串中的索引 |
public int lastIndexOf(int ch, int fromIndex); |
返回最后一次出现的指定字符在此字符串中的索引,从指定索引开始向后搜索 |
1-3.2.11 startsWith();
,endsWith(String suffix);
startsWith();
:测试此字符串是否以指定前缀开头。
endsWith();
:测试此字符串是否以指定的后缀结尾。
示例:
String str1 = "Hello world!";
String str2 = "你好世界!";
System.out.println("str1 是否以 Hello 为前缀?" + str1.startsWith("Hello"));
System.out.println("str2 是否以 Hello 为前缀?" + str2.startsWith("Hello"));
System.out.println("===============");
System.out.println("str1 是否以 world! 为后缀?" + str1.endsWith("world!"));
System.out.println("str2 是否以 ! 为后缀?" + str2.endsWith("!"));
System.out.println("===============");
得到:
str1 是否以 Hello 为前缀?true
str2 是否以 Hello 为前缀?false
===============
str1 是否以 world! 为后缀?true
str2 是否以 ! 为后缀?false
===============
startsWith();
方法的其他重载版本:
方法 | 行为 |
---|---|
public boolean startsWith(String prefix); |
测试此字符串是否以指定前缀开头 |
public boolean startsWith(String prefix, int toffset); |
测试从指定索引开始的此字符串的子字符串是否以指定前缀开头 |
1-3.2.12 toLowerCase();
,toUpperCase();
toLowerCase();
:使用默认locale的规则将此 String
中的所有字符转换为小写。
toUpperCase();
:使用默认locale的规则将此 String
中的所有字符转换为大写。
示例:
String str = "Hello world!";
System.out.println("转换为全小写:" + str.toLowerCase());
System.out.println("转换为全大写:" + str.toUpperCase());
得到:
转换为全小写:hello world!
转换为全大写:HELLO WORLD!
该方法的其他重载版本:
方法 | 行为 |
---|---|
public String toLowerCase(Locale locale); |
使用给定 Locale 的规则将此 String 中的所有字符转换为小写 |
public String toUpperCase(Locale locale); |
使用给定 Locale 的规则将此 String 中的所有字符转换为大写。 |
1-3.2.13 replace();
,replaceAll();
replace(char oldChar, char newChar);
:返回将此字符串中所有出现的 oldChar
替换为 newChar
的字符串(替换字符)。
replace(CharSequence target, CharSequence replacement);
:用给定的替换字符串,替换此字符串中与给定的 正则表达式 匹配的第一个子字符串。
replaceAll(String regex, String replacement);
:用给定的替换替换此字符串中与给定的 正则表达式 匹配的每个子字符串。
CharSequence
是 String
类所实现的一个接口,利用多态,可以向 replace()
的第二个重载版本传入字符串。
replace();
示例:
String str = "Hello Java!";
System.out.println("替换前:" + str);
System.out.println("替换后:" + str.replace("Java", "PHP"));
System.out.println("再次输出原字符串:" + str);
得到
替换前:Hello Java!
替换后:Hello PHP!
再次输出原字符串:Hello Java!
replaceAll();
示例:该方法传入参数支持正则表达式
String str = "Java是最好的编程语言,Java真香!";
System.out.println("原字符串:" + str);
System.out.println("替换全部:" + str.replaceAll("Java", "PHP"));
得到:
原字符串:Java是最好的编程语言,Java真香!
替换全部:PHP是最好的编程语言,PHP真香!
该方法的调用 str.replaceAll(regex, repl);
与下列语句所产生的结果完全相同:
Pattern.complile(regex).matcher(str).replaceAll(repl);
有关正则表达式,请见官方文档。
1-3.2.14 split(String regex);
描述:围绕给定正则表达式的匹配项拆分此字符串,返回一个字符串数组。
示例:
String str1 = "foo:and:boo";
String str2 = "Java is the best programming language, Java is nice!";
System.out.println("原字符串:" + str1);
System.out.println("拆分此串:" + Arrays.toString(str1.split(":")));
System.out.println("原字符串:" + str2);
//使用正则表达式拆分:以 " "和","拆分
System.out.println("拆分此串:" + Arrays.toString(str2.split("[ ,]")));
System.out.println(sep);
得到:
原字符串:foo:and:boo
拆分此串:[foo, and, boo]
原字符串:Java is the best programming language, Java is nice!
拆分此串:[Java, is, the, best, programming, language, , Java, is, nice!]
该方法的其他重载版本:
方法 | 行为 |
---|---|
public String[] split(String regex, int limit); |
围绕给定的正则表达式拆分此字符串。 |
limit
参数用于控制应用 pattern 的次数,影响返回的数组的长度:
- 若
limit
为正数,则 pattern 会最多应用limit - 1
次,所得数组长度将不大于limit
,数组的最后一个条目将包含最后一个定界符(delimiter)之外的所有输入; - 若
limit
为零,则 pattern 会尽可能多地应用,所得数组会拥有任意长度,尾随的空字符串将会被丢弃; - 若
limit
为负数,则 pattern 会尽可能多地应用,所得数组会拥有任意长度。
以字符串 foo:and:boo
为例:
//正则表达式 ":"
String str = "foo:and:boo";
System.out.println("原字符串:" + str);
System.out.println("正则表达式\":\",限制 2:" + Arrays.toString(str.split(":", 2)));
System.out.println("正则表达式\":\",限制 5:" + Arrays.toString(str.split(":", 5)));
System.out.println("正则表达式\":\",限制 -2:" + Arrays.toString(str.split(":", -2)));
System.out.println("===============");
System.out.println("正则表达式\"o\",限制 5:" + Arrays.toString(str.split("o", 2)));
System.out.println("正则表达式\"o\",限制 -2:" + Arrays.toString(str.split("o", -2)));
System.out.println("正则表达式\"o\",限制 0:" + Arrays.toString(str.split("o", 0)));
System.out.println("===============");
得到
原字符串:foo:and:boo
正则表达式":",限制 2:[foo, and:boo]
正则表达式":",限制 5:[foo, and, boo]
正则表达式":",限制 -2:[foo, and, boo]
===============
正则表达式"o",限制 5:[f, , :and:b, , ]
正则表达式"o",限制 -2:[f, , :and:b, , ]
正则表达式"o",限制 0:[f, , :and:b]
===============
该方法的调用 str.split(regex, n);
与下列语句所产生的结果完全相同:
Pattern.complile(regex).split(str,n);
有关正则表达式,请见官方文档。
1-3.2.15 concat();
描述:将指定的字符串连接到此字符串的末尾。
示例:
String str = "concat";
System.out.println("原字符串:" + str);
System.out.println("拼接后:" + str.concat("enation"));
得到
原字符串:Concat
拼接后:Concatenation
1-3.2.16 substring();
substring(int beginIndex);
:返回一个字符串,该字符串是此字符串的子字符串。
substring(int beginIndex, int endIndex);
:返回一个字符串,该字符串是此字符串的子字符串。子字符串从指定的 beginIndex
开始并扩展到索引 endIndex - 1
处的字符。因此子串的长度是 endIndex-beginIndex
。
注意:
substring(int beginIndex);
实际上调用的是第二个重载:substring(beginIndex, length());
;- 若
beginIndex
为负数,或endIndex
大于此字符串长度,或者beginIndex
大于endIndex
,则抛出异常IndexOutOfBoundsException
。
1-3.3 案例演示
满足以下需求:对于字符串 String str = "this is a text";
- 将字符串中的单词单独获取出来;
- 将
str
中的"text"
替换为"practice"
; - 在
"text"
前加上"easy"
; - 将每个单词的首字母改为大写。
实现:
public class CaseDemo {
public static void main(String[] args) {
String str = "this is a text";
//1. 单独提取每个单词
String[] arr = str.split(" ");
System.out.println(Arrays.toString(arr));
System.out.println("===============");
//2. 替换 text 为 practice
String str1 = str.replace("text", "practice");
System.out.println(str1);
System.out.println("===============");
//3. 在 text 前加上 easy
String str2 = str.replace("text", "easy text");
System.out.println(str2);
System.out.println("===============");
//4. 将单词首字母改为大写
for (int i = 0; i < arr.length; i++) {
//提取每个单词的首字母,利用包装类转换成大写
char first = arr[i].charAt(0);
char firstUpperCase = Character.toUpperCase(first);
//拼接
//substring()
arr[i] = firstUpperCase + arr[i].substring(1);
}
String str3 = "";
for (int i = 0; i < arr.length; i++) {
str3 = str3.concat(arr[i] + " ");
}
str3.trim();
System.out.println(str3);
}
}
运行,得到
[this, is, a, text]
===============
this is a practice
===============
this is a easy text
===============
This Is A Text