一、方法定义
public synchronized StringBuffer setCharAt(int index, char ch)
参数说明:
index
:要设置字符的位置索引(从0开始)。ch
:要设置的字符值。
返回值:
- 返回当前
StringBuffer
对象的引用(支持链式调用)。
异常:
IndexOutOfBoundsException
:如果index
小于 0 或大于等于当前字符串的长度(length()
)。
二、功能说明
setCharAt()
方法用于将 StringBuffer
中指定索引位置的字符替换为新的字符。该操作是原地修改,不会创建新的对象。
核心特点:
- ✅ 线程安全:方法被
synchronized
修饰,可在多线程环境中安全调用。 - ✅ 高效修改:直接修改内部字符数组,性能优于替换子串。
- ✅ 支持链式调用:返回
this
,可连续调用其他方法。 - ✅ 单字符替换:只能修改一个字符,不能插入或删除。
三、示例代码
示例 1:基本字符替换
StringBuffer sb = new StringBuffer("hello");
sb.setCharAt(0, 'H'); // 将第一个字符 'h' 改为 'H'
System.out.println(sb.toString()); // 输出:Hello
示例 2:修改中间字符
StringBuffer sb = new StringBuffer("Java");
sb.setCharAt(2, 'v'); // 'v' 已是原字符,无变化
sb.setCharAt(1, 'a'); // 将 'a' 改为 'a'(无变化)
sb.setCharAt(3, '!'); // 将 'a' 改为 '!'
System.out.println(sb.toString()); // 输出:Jav!
示例 3:链式调用
StringBuffer sb = new StringBuffer("test");
sb.setCharAt(0, 'T')
.setCharAt(1, 'E')
.setCharAt(2, 'S')
.setCharAt(3, 'T');
System.out.println(sb.toString()); // 输出:TEST
示例 4:异常处理(索引越界)
StringBuffer sb = new StringBuffer("abc");
try {
sb.setCharAt(5, 'x'); // 索引5超出范围[0,2]
} catch (IndexOutOfBoundsException e) {
System.out.println("错误:" + e.getMessage());
}
示例 5:修改数字字符串中的某一位
StringBuffer sb = new StringBuffer("12345");
sb.setCharAt(2, '0'); // 将 '3' 改为 '0'
System.out.println(sb.toString()); // 输出:12045
四、使用技巧
技巧 1:实现字符串“加密”或掩码
StringBuffer sb = new StringBuffer("password123");
for (int i = 0; i < sb.length() - 4; i++) {
sb.setCharAt(i, '*');
}
System.out.println(sb.toString()); // 输出:*******123
技巧 2:反转字符串(配合循环)
StringBuffer sb = new StringBuffer("reverse");
int n = sb.length();
for (int i = 0; i < n / 2; i++) {
char temp = sb.charAt(i);
sb.setCharAt(i, sb.charAt(n - 1 - i));
sb.setCharAt(n - 1 - i, temp);
}
System.out.println(sb.toString()); // 输出:esrever
技巧 3:校验并修改特定字符
StringBuffer sb = new StringBuffer("user@email");
// 将非法字符 '@' 改为 '.'
for (int i = 0; i < sb.length(); i++) {
if (sb.charAt(i) == '@') {
sb.setCharAt(i, '.');
}
}
System.out.println(sb.toString()); // 输出:user.email
五、常见错误
❌ 错误 1:索引越界
StringBuffer sb = new StringBuffer("a");
sb.setCharAt(1, 'b'); // 抛出 IndexOutOfBoundsException
原因:有效索引为
[0, length()-1]
,即只有0
。
❌ 错误 2:负索引
sb.setCharAt(-1, 'x'); // 直接抛出异常
❌ 错误 3:空 StringBuffer 调用
StringBuffer sb = new StringBuffer();
sb.setCharAt(0, 'a'); // 抛出异常,长度为0
六、注意事项
- ✅ 索引从0开始,最大有效索引为
length() - 1
。 - ✅ 不能用于插入字符:目标位置必须已存在字符。
- ✅ 线程安全:多线程可安全调用,但性能低于
StringBuilder
。 - ⚠️ 性能良好:直接操作内部数组,时间复杂度 O(1)。
- ✅ 字符值无限制:
ch
可以是任意char
值,包括 Unicode 字符。
七、最佳实践
✅ 实践 1:预检查长度再修改
StringBuffer sb = new StringBuffer("data");
int index = 2;
if (index >= 0 && index < sb.length()) {
sb.setCharAt(index, 'X');
} else {
System.out.println("索引无效");
}
✅ 实践 2:在多线程中安全修改
// 多个线程可安全修改不同位置
Thread t1 = () -> sb.setCharAt(0, 'A');
Thread t2 = () -> sb.setCharAt(1, 'B');
t1.start(); t2.start();
✅ 实践 3:避免在循环中频繁修改(高并发)
- 虽然
setCharAt
是 O(1),但synchronized
可能成为瓶颈。 - 高并发场景可考虑先用
StringBuilder
处理,再赋值。
八、性能优化建议
单线程优先使用 StringBuilder:
// 单线程场景 StringBuilder sb = new StringBuilder("text"); sb.setCharAt(0, 'T'); // 更快,无同步开销
批量修改时考虑 replace():
- 若需修改连续多个字符,使用
replace(start, end, str)
更高效。
- 若需修改连续多个字符,使用
预设容量减少扩容:
StringBuffer sb = new StringBuffer(100); // 预分配
总结
项目 | 说明 |
---|---|
核心功能 | 安全修改指定位置的单个字符 |
关键特性 | 线程安全、原地修改、O(1) 时间复杂度 |
适用场景 | 动态文本微调、掩码处理、字符校验 |
使用技巧 | 可用于掩码、反转、条件替换 |
性能提示 | 单线程用 StringBuilder 更优,避免越界 |
常见错误 | 索引越界、空对象调用 |
💡 一句话总结:
StringBuffer.setCharAt(index, ch)
是一个线程安全的单字符替换方法,适用于多线程环境下的精确字符修改。注意索引边界,单线程场景推荐使用StringBuilder.setCharAt()
以获得更高性能。