Java String类用法详解(附带实例,新手必看)
String 类位于 java.lang 包中,lang 包中的类无须导入,因此 String 类可直接使用。
Java String类初始化
在使用 String 类进行字符串操作之前,首先需要进行初始化。Java 中对 String 类的初始有两种方式,具体如下:
1) 直接给变量赋字符串常量值。使用字符串常量直接赋值给一个 String 对象,具体语法格式下:
String 变量名 = "字符串内容"
2) 使用构造方法进行初始化。String 类的构造方法有多个,常用的构造方法如下表所示。
方法 | 方法描述 |
---|---|
String() | 创建一个空的字符串对象,即字符串长度为0,但不代表对象为null |
String(String original) | 根据一个字符串常量值来创建一个字符串对象 |
String(char value[]) | 将char数组中的元素拼接成一个字符串对象 |
String(char value[], int offset, int count) | 将一个char数组截取一定的范围转换成一个字符串对象,其中第1个参数是char数组,第2个参数是截取开始的下标,第3个参数为截取的位数 |
String(byte[] bytes) | 将一个byte数组转换成一个字符串对象 |
String(byte bytes[], int offset, int length) | 将一个byte数组截取一定的范围转换成一个字符串对象,其中第1个参数是byte数组,第2个参数是截取开始的下标,第3个参数为截取的位数 |
String(byte bytes[], int offset, int length, String charsetName) | 同上一个方法,区别在于上一个是按照平台默认编码格式进行转换,而这个是按照指定编码格式进行转换 |
接下来,通过案例来演示 String 类的多种构造方法的使用:
public class Demo { public static void main(String[] args) { String str = new String(); // 创建一个空的字符串 String str0 = new String("abcd"); // 创建一个字符串对象 System.out.println("根据字符串常量创建结果: " + str0); char[] chars = {'a', 'b', 'c', 'd'}; String str1 = new String(chars); // 由字符数组创建一个字符串 System.out.println("char数组转换结果: " + str1); String str2 = new String(chars, 1, 2); // 截取字符数组,转换成字符串 System.out.println("char数组从1开始转换2位的结果: " + str2); byte[] bytes = {65, 66, 67, 68}; String str3 = new String(bytes); // 由字节数组转换成字符串对象 System.out.println("byte数组转换结果: " + str3); String str4 = new String(bytes, 1, 2); // 截取字节数组,转换成字符串 System.out.println("byte数组从1开始转换2位的结果: " + str4); } }程序的运行结果如下:
根据字符串常量创建结果:abcd
char数组转换结果:abcd
char数组从1开始转换2位的结果:bc
byte数组转换结果:ABCD
byte数组从1开始转换2位的结果:BC
使用第一种“=”赋值常量的形式,JVM 会去字符串常量池中查找是否存在对应常量值:
- 如果不存在,就在字符串常量池中开辟一个空间来存储;
- 如果存在,则该变量直接指向该常量值在字符串常量池中的地址值即可。
并且,每一次变量值更改不会改变现在这个常量值,而是重新在字符串常量池中查找,没有就重新开辟空间存储,因此字符串是不可变的,每次改变都是地址的重新开辟。
接下来,我们可以声明两个变量存储相同的内容,输出“==”比对的结果来观察一下地址存储的情况:
public class Demo { public static void main(String[] args) { String str = "abcd"; String str1 = "abcd"; System.out.println(str == str1); // 结果为true str1 = "abcde"; System.out.println(str == str1); // 结果为false System.out.println("str的值:" + str); System.out.println("str1的值:" + str1); } }程序的运行结果如下:
true
false
str的值:abcd
str1的值:abcde

图 1 str和str1的地址变化
如果 str1 的值更改为 abcde,并不会更改现在这个地址的里的内容,而是重新查找是否含有 abcde,如果有则指向,如果没有则重新开辟一个空间存储,然后指向新的地址,内存显示如图 1(b)所示。
注意,使用“==”关系运算符比较基本数据类型,可以用来判断值是否相同;如果比较的是引用数据类型,判断的是引用地址是否相同。
使用第 2 种形式,即 new 关键字调用构造方法,则每次初始化字符串对象都会在堆区开辟一个新的空间,因此使用 new 创建字符串对象无论内容是否一致,都会开辟不同的空间来存储。
接下来,我们可以使用 new 创建两个内容一致的字符串对象,输出“==”比对的结果来观察一下地址存储的情况,代码如下:
public class Demo { public static void main(String[] args) { String str = new String("abcd"); String str1 = new String("abcd"); System.out.println("str==str1结果为:" + (str == str1)); // 结果为false } }程序的运行结果如下:
str==str1结果为:false
程序中 str 和 str1 字符串的内容相同,“==”对比的结果为 false,说明两者指向的地址是不同的,即使用 new 创建字符串对象,每次都会开辟一个新的空间。Java String类的常用方法
对于已经声明并且初始化的字符串,可以对其进行拼接、截取、判断长度等操作。1) 字符串判断比较
在 Java 程序开发中,字符串判断比较是最常见的问题。通过前文的学习,我们已经知道使用“==”可以比较两个字符串的地址是否相同,但是实际开发过程中所涉及的字符串判断比较并不都是简单的地址对比,需要进行更全面、复杂的判断比较。为此,Java 提供了丰富的字符串判断比较方法,最常用的如下表所示:
方法 | 方法描述 |
---|---|
int compareTo(String anotherString) | 按字符的 ASCII 码值对字符串进行大小比较,返回整数值。若当前对象比参数大则返回正整数,反之则返回负整数,相等则返回 0。比较时先比较第 1 个字符,如果一样再比较第 2 个,以此类推 |
int compareToIgnoreCase(String anotherString) | 与compareTo() 方法相似,但忽略大小写 |
boolean equals(Object anotherObject) | 该方法用来比较当前字符串和参数字符串中存储的内容是否一致,一致时返回 true,否则返回 false。与之前介绍的“==”不同,“==”比较的是地址,而 equals() 比较的是地址中存储的值 |
boolean equalsIgnoreCase(String anotherString) | 与 equals() 方法相似,但忽略大小写 |
boolean startsWith(String prefix) | 测试当前字符串是否以指定参数开头 |
boolean endsWith(String suffix) | 测试当前字符串是否以指定参数结尾 |
boolean isEmpty() | 判断字符串是否为空,即字符串的长度如果为 0 则返回 true,否则返回 false |
boolean contains(CharSequence s) | 判断当前字符串中是否包含参数子串 |
接下来,通过案例来演示字符串判断比较方法的使用:
public class Demo { public static void main(String[] args) { String str = new String("AAA"); String str1 = new String("AAA"); String str2 = new String("aaa"); System.out.println("str==str1结果:" + (str == str1)); System.out.println("str.equals(str1)结果:" + str.equals(str1)); System.out.println("str.equals(str2)结果:" + str.equals(str2)); boolean result1 = str.equalsIgnoreCase(str2); System.out.println("str.equalsIgnoreCase(str2)结果:" + result1); System.out.println("str.compareTo(str1)结果:" + str.compareTo(str1)); System.out.println("str.compareTo(str2)结果:" + str.compareTo(str2)); int result2 = str.compareToIgnoreCase(str2); System.out.println("str.compareToIgnoreCase(str2)结果:" + result2); String str3 = "C语言中文网教育14年!"; System.out.println("str3.startsWith(\"A\")结果:" + str3.startsWith("A")); System.out.println("str3.endsWith(\"!\")结果:" + str3.endsWith("!")); System.out.println("str3.contains(\"a\")结果:" + str3.contains("a")); String str4 = ""; // 如果长度为0则返回true System.out.println("str4.isEmpty()结果为:" + str4.isEmpty()); } }程序的运行结果如下:
str==str1结果:false
str.equals(str1)结果:true
str.equals(str2)结果:false
str.equalsIgnoreCase(str2)结果:true
str.compareTo(str1)结果:0
str.compareTo(str2)结果:-32
str.compareToIgnoreCase(str2)结果:0
str3.startsWith("A")结果:false
str3.endsWith("!")结果:true
str3.contains("a")结果:false
str4.isEmpty()结果为:true
str 存储的是“AAA”,而 str2 存储的是“aaa”,大小写不同,所以 equals() 对比结果为 false,而 equalsIgnoreCase() 忽略大小写对比返回的是 true。
str 和 str1 存储内容完全一致,因此 compareTo() 返回值为 0。str 和 str2 的大小写不同,compareTo() 对比结果是 –32,因为“A”的 ASCII 值为 65,而“a”的 ASCII 值为 97,两数之差是 –32。
CompareToIgnoreCase() 忽略大小写比较,因此“AAA”和“aaa”对比结果为 0。
第 22 行中,str4 对象必须非 null,否则会出现空指针异常,因为 isEmpty() 方法底层是调用 length() 方法,如果长度为 0 则返回 true,否则返回 false。
注意,使用“==”对比的是地址,new 方式初始化的字符串,里边的内容即便相同返回的也是 false,因此在不能明确初始化方式是“=”赋值常量的情况下,不建议使用“==”来判断字符串是否相同,而要用 equals() 方法来比较存储的内容是否一致。
2) 字符串连接
字符串连接指的是将多个字符串拼接组成一个字符串。Java中提供两种方式进行字符串拼接:- “+”拼接:使用“+”可以实现多个字符串连接形成一个新的字符串对象,并且如果“+”连接的是一个字符串和一个其他类型数据,返回的结果也是字符串。
- String concat(String str)方法:将参数中的字符串 str 连接到当前字符串的后面,效果等价于使用“+”。
接下来,通过案例来演示字符串的拼接:
public class Demo { public static void main(String[] args) { String str1 = "C语言"; String str2 = "中文网"; String str = str1 + str2; // "+"拼接字符串 System.out.println("str1+str2:" + str); String str4 = str + 10 + 4 + "年"; System.out.println("str+14+\"年\":" + str4); String str5 = 10 + 4 + "年"; // 字符串数字混合运算,从左往右运行 System.out.println("10+4+\"年\":" + str5); String str6 = str + (10 + 4) + "年"; // ()提高优先级,先计算()内再和字符串拼接 System.out.println("str+(10+4)+\"年\":" + str6); str6 += "!"; // 同于str6 = str6 + "!" System.out.println("str6+=\"!\":" + str6); String str7 = str1.concat(str2).concat("教育").concat("14年!"); System.out.println("concat拼接:" + str7); // 同于str1 + str2 + "教育" + "10年!" } }程序的运行结果如下:
str1+str2:C语言中文网
str+14+"年":C语言中文网104年
10+4+"年":14年
str+(10+4)+"年":C语言中文网14年
str6+="!":C语言中文网14年!
concat拼接:C语言中文网教育14年!
- “10 + 4 + "年"”的拼接结果为“14年”,即两个数字在前,那么结果是先数字运算,再和字符串拼接;
- “"C语言中文网" + 10 + 4 + "年"”的拼接结果为“C语言中文网104年”,说明如果数字在字符串后面,那么直接和字符串拼接,不会进行数学运算。但是,案例也显示,可以通过添加()使中间的数字先进行数学运算,再进行字符串拼接。
注意,String 对象是不可变的,因此每次“+”拼接的结果都会在字符串常量池中产生新的字符串常量,如果需要频繁地拼接字符串,不建议使用 String 类,空间浪费;如果是字符串和数字的混合运算,从左往右依次运算,从碰到字符串的位置开始按照字符串拼接走。
3) 提取字符串基本信息
字符串作为一个对象,可以通过该对象提供的特有方法来获取字符串的一些基本信息,如字符串长度、指定位置的字符等,具体方法如下表所示。方法 | 方法描述 |
---|---|
int length() | 返回字符串长度,即字符的个数 |
char charAt(int index) | 获取索引位置的字符,index是索引下标,如果下标超出长度,会报错,其中索引从0开始 |
接下来,通过案例来演示提取字符串的基本信息:
public class Demo { public static void main(String[] args) { String str = "C语言中文网14年"; int length = str.length(); System.out.println("length():" + length); char ch = str.charAt(3); System.out.println("charAt(3):" + ch); char ch2 = str.charAt(10); System.out.println("charAt(10):" + ch2); } }程序的运行结果如下:
length():9 charAt(3):中 Exception in thread "main" java.lang.StringIndexOutOfBoundsException: index 10,length 9 at java.base/java.lang.String.checkIndex(String.java:3679) at java.base/java.lang.StringUTF16.checkIndex(StringUTF16.java:1587) at java.base/java.lang.StringUTF16.charAt(StringUTF16.java:1384) at java.base/java.lang.String.charAt(String.java:711) at Main.main(Main.java:8)程序中 length 取值为字符的个数,与中英文无关;charAt() 获取指定位置的字符,超出索引范围会报错。
4) 提取子串
提取子串从本质上来说就是截取字符串的意思,即从一个特定的字符串中截取一定长度的子串。String类中提供了两个截取字符串的方法,一个是从指定位置开始,截取到该字符串的尾部;另一个是在指定范围内进行截取,具体方法如下表所示。
方法 | 方法描述 |
---|---|
String substring(int beginIndex) | beginIndex 位置起,从当前字符串中取出剩余的字符作为一个新的字符串返回 |
String substring(int beginIndex, int endIndex) | beginIndex 位置起到 endIndex 位置停,从当前字符串中取出该范围的字符作为一个新的字符串返回。子串中包含 beginIndex 但不包含 endIndex 位置的内容 |
接下来,通过案例来演示提取子串,即截取字符串:
public class Demo { public static void main(String[] args) { String str = "C语言中文网14年"; String sub1 = str.substring(1); // 从下标1开始截取,截取到尾部 System.out.println("substring(1):" + sub1); String sub2 = str.substring(1, 3); // 从下标1开始截取,截取到下标3(不包含3) System.out.println("substring(1,3):" + sub2); } }程序的运行结果如下:
substring(1):语言中文网14年
substring(1,3):语言
需要注意的是,字符串的下标是从 0 开始的。
5) 字符串的字符查找
在日常开发中,经常会遇到需要判断字符串中是否包含另外一个字符串(子串)或者某个字符的情况。String 类提供了 indexOf() 和 lastIndexOf() 方法来查找某个特定字符或者字符串(子串)在另一个字符串中出现的位置,具体如下表所示。
方法 | 方法描述 |
---|---|
int indexOf(int ch/String str) | 返回参数字符或者字符串在当前字符串中首次出现的索引位置。调用该方法,会从字符串的开始位置开始检索字符或者字符串,如果没有检索到返回 -1,检索到返回首次找到的索引。其中,“int ch”代表的是字符的 ASCII 码值,“String str”是一个子串 |
int indexOf(int ch/String str, int fromIndex) | 该方法与上一个方法类似,区别在于它不是从头开始检索,而是从指定位置 fromIndex 处开始查找 |
int lastIndexOf(int ch/String str) | 返回参数字符或者字符串在当前字符串中最右边出现的索引,即从右侧开始查找第一次出现的位置 |
int lastIndexOf(int ch/String str, int fromIndex) | 该方法与上一个方法类似,区别在于它不是从最右侧开始检索,而是从指定的索引 fromIndex 开始从右往左进行查找 |
接下来,通过案例来演示字符串的字符查找:
public class Demo { public static void main(String[] args) { String str = "C语言中文网14年,专注教育14年"; int sub1 = str.indexOf(49); // '1'的ASCII值为49 System.out.println("indexOf(49)结果为:" + sub1); int sub11 = str.indexOf("1"); System.out.println("indexOf(\"1\")结果为:" + sub11); int sub12 = str.indexOf("1", 10); System.out.println("indexOf(\"1\",10)结果为:" + sub12); int sub13 = str.lastIndexOf("1"); System.out.println("lastIndexOf(\"1\")结果为:" + sub13); int sub14 = str.lastIndexOf("1", 14); // 从14往前找,倒着找第一次出现1的位置 System.out.println("lastIndexOf(\"1\",14)结果为:" + sub14); } }程序的运行结果如下:
indexOf(49)结果为:6
indexOf("1")结果为:6
indexOf("1",10)结果为:14
lastIndexOf("1")结果为:14
lastIndexOf("1",14)结果为:14
6) 字符串替换
在日常开发中,经常会遇到需要将字符串中的一个或多个子串替换成其他字符串的需求,如新闻中的一些敏感词汇替换成“*”等。String 类提供了 replace()、replaceFirst() 以及 replaceAll() 方法来实现字符串替换功能,具体如下表所示。
方法 | 方法描述 |
---|---|
String replace(CharSequence target, CharSequence replacement) | 该方法可以实现将指定字符序列(target)替换成新的字符序列(replacement),并返回一个新的字符串。CharSequence 是一个接口,代表一个字符序列,String 类、StringBuffer 类、StringBuilder 类都实现了这个接口 |
String replaceFirst(String regex, String replacement) | 该方法用来将第 1 个指定的字符串或者第 1 个匹配的子串(regex)替换成新的字符串(replacement),支持正则表达式 |
String replaceAll(String regex, String replacement) | 该方法用来将所有指定的字符串或者匹配的子串(regex)替换成新的字符串(replacement),支持正则表达式 |
接下来,通过案例来演示字符串的替换:
public class Demo { public static void main(String[] args) { String str = "C语言中文网14年,专注教育14年"; String newStr = str.replace("14", "十四"); // 将所有的14替换成十四 System.out.println("replace替换后的字符串:" + newStr); String newStr1 = str.replaceFirst("14", "十四"); // 将第1个14替换成十四 System.out.println("replaceFirst替换后的字符串:" + newStr1); String newStr2 = str.replaceAll("14", "十四"); // 将匹配的子串全部替换 System.out.println("replaceAll根据字符串替换结果:" + newStr2); String newStr3 = str.replaceAll("1.", "十四"); // 将匹配正则的内容全部替换 System.out.println("replaceAll根据正则表达式替换结果:" + newStr3); System.out.println("替换前字符串:" + str); // 所有操作不影响原对象 } }程序的运行结果如下:
replace替换后的字符串:C语言中文网十四年,专注教育十四年
replaceFirst替换后的字符串:C语言中文网十四年,专注教育14年
replaceAll根据字符串替换结果:C语言中文网十四年,专注教育十四年
replaceAll根据正则表达式替换结果:C语言中文网十四年,专注教育十四年
替换前字符串:C语言中文网14年,专注教育14年
程序中所有的替换都没有影响原来的字符串,返回了一个新的字符串对象。
7) 字符串中字符的大小写转换
String 类提供了 toLowerCase() 方法用于将当前字符串中的所有字符转换成小写;同时,也提供了 toUpperCase() 方法用于将当前字符串中所有的字符转换成大写。接下来,通过案例来演示字符串的大小写转换:
public class Demo { public static void main(String[] args) { String str = "C语言中文网14年,专注教育14年"; String strLow = str.toLowerCase(); System.out.println("toLowerCase调用转换后:" + strLow); String strUpper = strLow.toUpperCase(); System.out.println("toUpperCase调用转换后:" + strUpper); } }程序的运行结果如下:
toLowerCase调用转换后:c语言中文网14年,专注教育14年
toUpperCase调用转换后:C语言中文网14年,专注教育14年
8) 去除两端空格
在日常开发中,可能会遇到需要将某个字符串两端的空格去除这样的问题,比如接收录入的参数中含有前后空格,就需要将其去除。String 类提供了 trim() 方法,用于截去字符串两端的空格,但对于中间的空格不处理。
接下来,通过案例来演示去除字符串的两端空格:
public class Demo { public static void main(String[] args) { String str = " C语言中文网14年 专注教育14年 "; // 前一个空格,后一个空格,中间一个空格 System.out.println(str + "----的长度为:" + str.length()); String strTrim = str.trim(); System.out.println(strTrim + "----的长度为:" + strTrim.length()); } }程序的运行结果如下:
C语言中文网14年 专注教育14年 ----的长度为:19
C语言中文网14年 专注教育14年----的长度为:17
9) 分隔符进行字符串分解
String 类提供了 split(String str) 方法,该方法可将参数 str 作为分隔符进行字符串分解,分解后返回的是一个字符串数组。接下来,通过案例来演示字符串的分解:
public class Demo { public static void main(String[] args) { String str = "C语言中文网,Java教程,Python教程,C#教程"; String[] strs = str.split(","); for(int i = 0; i < strs.length; i++) { System.out.println("第" + i + "个字符串是:" + strs[i]); } } }程序的运行结果如下:
第0个字符串是:C语言中文网
第1个字符串是:Java教程
第2个字符串是:Python教程
第3个字符串是:C#教程