Java字符串处理String、StringBuffer、StringBuilder完全详解
在Ja va编程中,字符串处理是绕不开的基础。无论是处理用户输入、文件内容还是网络数据,对String类及其相关工具的理解深度,直接决定了代码的效率和优雅程度。今天,我们就来系统地梳理一下Ja va字符串的核心知识,从String的常用方法,到它与各类数据的转换,再到StringBuffer和Str
在Ja va编程中,字符串处理是绕不开的基础。无论是处理用户输入、文件内容还是网络数据,对String类及其相关工具的理解深度,直接决定了代码的效率和优雅程度。今天,我们就来系统地梳理一下Ja va字符串的核心知识,从String的常用方法,到它与各类数据的转换,再到StringBuffer和StringBuilder的灵活运用。
1、String类的常用方法
String类提供了丰富的方法来操作字符串,我们可以将其分为几个功能模块来理解。
1.1 获取字符串信息
首先,了解一个字符串的基本信息是操作的起点。
int length() 方法直接返回字符串的长度,这是最常用的属性之一。
int len = str.length();
如果想获取特定位置的字符,就用 char charAt(int index)。记住,索引是从0开始的。
char c = str.charAt(0);
判断一个字符串是否为空,除了检查是否为null,更规范的做法是使用 boolean isEmpty(),它检查的是长度是否为0。
boolean empty = str.isEmpty();
1.2 大小写转换
处理用户输入或进行字符串比较时,大小写转换很常见。String toLowerCase() 和 String toUpperCase() 分别用于转换为小写和大写,默认使用系统语言环境。
String lower = str.toLowerCase(); String upper = str.toUpperCase();
1.3 字符串处理
清理和截取字符串是日常操作。String trim() 可以去除首尾的空白字符,在处理用户输入时尤其有用。
String result = str.trim();
截取子串有两个重载方法:String substring(int beginIndex) 从指定位置截到末尾;而 String substring(int beginIndex, int endIndex) 则截取一个左闭右开的区间。
String sub = str.substring(2); String subRange = str.substring(2, 5);
1.4 字符串比较
字符串比较切忌使用 ==。内容比较应该使用 boolean equals(Object obj)。如果需要忽略大小写,就用 boolean equalsIgnoreCase(String anotherString)。
boolean flag = str1.equals(str2); boolean flagIgnoreCase = str1.equalsIgnoreCase(str2);
如果要进行排序或判断字典序,int compareTo(String anotherString) 会返回一个整数,表示两个字符串的大小关系。
int result = str1.compareTo(str2);
1.5 字符串拼接
虽然“+”操作符最常用,但 String concat(String str) 方法功能与之等价。需要注意的是,String对象是不可变的,这些操作都会产生新的字符串对象。
String result = str1.concat(str2); // 等价于 String result = str1 + str2;
1.6 字符串查找与匹配
判断字符串的开头或结尾,可以使用 boolean startsWith(String prefix) 和 boolean endsWith(String suffix)。startsWith 还有一个重载方法,可以指定从哪个索引开始检查。
String str1 = "helloworld";
boolean b1 = str1.endsWith("rld");
boolean b2 = str1.startsWith("He");
boolean b3 = str1.startsWith("ll", 2);
检查是否包含某个子序列,用 boolean contains(CharSequence s)。
System.out.println(str1.contains("wor"));
查找子串的位置则有一组“indexOf”方法:int indexOf(String str) 从头找第一次出现的位置;int indexOf(String str,int fromIndex) 从指定位置开始找。相对应的,int lastIndexOf(String str) 和 int lastIndexOf(String str,int fromIndex) 是从字符串末尾开始反向搜索。所有查找方法如果没找到,都会返回 -1。
System.out.println(str1.indexOf("lo"));
System.out.println(str1.indexOf("lo",5));
System.out.println(str3.lastIndexOf("or"));
System.out.println(str3.lastIndexOf("or", 6));
1.7 字符串替换方法
简单的字符或字符序列替换,可以使用 String replace(char oldChar,char newChar) 和 String replace(CharSequence target, CharSequence replacement)。它们会替换所有匹配项。
String str1 = "咕噜咕噜咚";
String str2 = str1.replace('咕','嘟');
String str3 = str1.replace("咕噜", "嘟呜");
1.8 正则匹配与替换
当需要更复杂的模式匹配和替换时,就需要正则表达式出马了。String replaceAll(String regex, String replacement) 和 String replaceFirst(String regex, String replacement) 分别用于替换所有匹配项和第一个匹配项。
String str = "123ja va456mysql21345spring215mybatis4444";
// 把字符串中的数字替换成逗号,并去掉开头结尾多余的逗号
String string = str.replaceAll("\\d+",",").replaceAll("^,|,$","");
而 boolean matches(String regex) 则用于判断整个字符串是否完全匹配给定的正则表达式,常用于数据验证。
String tel = "0571-4534289";
boolean result = tel.matches("0571-\\d{7,8}"); // 判断是否为杭州固定电话格式
1.9 字符串拆分
将字符串按特定分隔符拆分成数组,是解析数据的常见操作。String[] split(String regex) 根据正则表达式拆分。如果想限制拆分后的段数,可以使用重载方法 String[] split(String regex,int limit),超过限制的部分会全部放入最后一个元素。
String str = "hello|world|ja va";
String[] strs = str.split("\\|");
String str2 = "hello.world.ja va";
String[] strs2 = str2.split("\\.");
2、String与基本数据类型转换
字符串和基本类型之间的转换是数据处理的桥梁,这里的关键在于调用正确的API。
- 字符串 → 基本数据类型/包装类:使用对应包装类的静态方法,如
Integer.parseInt(String s)。前提是字符串必须由“数字”字符组成,否则会抛出NumberFormatException。Byte、Short、Long、Float、Double等类都有类似方法。 - 基本数据类型/包装类 → 字符串:最常用的方法是
String.valueOf()系列静态方法,它支持各种基本类型参数。当然,直接用 “+” 连接空字符串也是一种简洁写法。
String str1 = "123"; // 字符串 -> int int num = Integer.parseInt(str1); // int -> 字符串 String str2 = String.valueOf(num); String str3 = num + ""; // 另一种常见写法
2.1 String与字符数组之间的转换
字符串 → 字符数组
调用 toCharArray() 是最直接的方式。如果需要更精细的控制,比如只复制一部分,可以使用 getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) 方法。
String str1 = "abc123"; // 使用 getChars char[] charArray1 = new char[str1.length()]; str1.getChars(0, 6, charArray1, 0); // 使用 toCharArray char[] charArray = str1.toCharArray();
字符数组 → 字符串
直接利用String的构造器即可:String(char[]) 或 String(char[],int offset,int length)。
char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr); // "hello"
String str3 = new String(arr, 1, 3); // "ell"
2.2 String与字节数组之间的转换
这涉及到编码和解码,是处理文本文件、网络传输时容易出乱码的地方。
字符串 → 字节数组(编码)
将字符串转换为字节序列。使用 getBytes()(默认字符集)或 getBytes(String charsetName)(指定字符集,如“GBK”、“UTF-8”)。
String str1 = "abc123中国";
byte[] bytes = str1.getBytes(); // 默认字符集
byte[] gbks = str1.getBytes("gbk"); // 指定GBK编码
字节数组 → 字符串(解码)
将字节序列还原为字符串。使用String的构造器 String(byte[]) 或 String(byte[],int offset,int length),同样可以指定字符集。
String s = new String(bytes); // 用默认字符集解码 String s1 = new String(gbks, "gbk"); // 用GBK解码,正确还原 String s2 = new String(gbks); // 用默认字符集解码GBK编码的字节,很可能乱码
这里有个至关重要的原则:解码时使用的字符集必须与编码时使用的字符集一致,否则一定会出现乱码。 这解释了为什么从网络或文件读取文本时,指定正确的字符集如此重要。
3、String/StringBuffer/StringBuilder类
3.1 String、StringBuffer、StringBuilder三者的异同
这是面试高频考点,核心区别在于可变性和线程安全性。
- String:不可变的字符序列。底层用
final char[]存储。任何修改操作都会生成新对象。适用于字符串内容不常变的场景。 - StringBuffer:可变的字符序列。线程安全(方法大多用
synchronized修饰),因此效率相对较低。底层使用char[]存储,可动态扩容。 - StringBuilder:可变的字符序列。JDK 5.0引入,线程不安全,但效率最高。底层实现与StringBuffer类似。在单线程环境下,优先推荐使用StringBuilder。
3.2 StringBuffer源码分析
理解源码能帮你更好地使用它。创建一个StringBuffer对象时,如果使用无参构造器,底层会初始化一个长度为16的字符数组。如果使用带字符串的构造器,数组长度会是“字符串长度 + 16”。
StringBuffer sb1 = new StringBuffer(); // char[] value = new char[16];
sb1.append('a'); // value[0]='a';
StringBuffer sb2 = new StringBuffer("abc"); // char[] value = new char["abc".length() + 16];
两个常见问题:
length()方法返回的是实际字符数(这里是3),而不是底层数组容量。- 扩容机制:当添加的数据导致数组容量不足时,会进行扩容。默认扩容为“原容量 * 2 + 2”,并将原有元素复制到新数组。因此,如果能够预估最终大小,建议使用
StringBuffer(int capacity)或StringBuilder(int capacity)指定初始容量,以减少扩容次数,提升性能。
3.3 StringBuffer中的常用方法
StringBuffer和StringBuilder的API基本一致,这里以StringBuffer为例。
3.3.1 字符串操作方法
- 增(append):最核心的方法,支持各种数据类型,用于拼接字符串。
- 删(delete):
delete(int start, int end),删除左闭右开区间的字符。 - 改(replace/setCharAt):
replace(int start, int end, String str)替换区间;setCharAt(int n, char ch)修改单个字符。 - 插(insert):
insert(int offset, xxx)在指定位置插入。 - 反转(reverse):
reverse()将序列反转。
这些方法(除了查询类)的一个共同特点是:它们都返回StringBuffer对象本身(即this)。这就使得方法链调用(Method Chaining)成为可能,让代码更简洁。
sb.append("a").append("b").insert(1, "-").reverse();

3.3.2 查询相关方法
查询方法与String类似,用于获取状态或内容:
int indexOf(String str):查找子串位置。String substring(int start, int end):截取子串。int length():返回长度。char charAt(int n):获取字符。void setCharAt(int n, char ch):设置字符。
方法总结口诀:
增:append(xxx)
删:delete(int start,int end)
改:setCharAt(n,ch) / replace(start, end, str)
查:charAt(n)
插:insert(offset,xxx)
长度:length()
遍历:for()+charAt() 或先 toString() 再处理。
总结
总的来说,Ja va字符串处理的三驾马车各有其职:String 适用于不变字符串,安全且简单;StringBuffer 用于需要线程安全的频繁修改场景;StringBuilder 则是单线程下修改字符串的性能首选。掌握它们的方法、转换规则以及底层原理,不仅能写出更高效的代码,也能在遇到编码、乱码、性能问题时,做到心中有数,快速定位。希望这份梳理能帮助你构建起清晰的字符串知识体系。
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















