1. 方法定义
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
2. 功能说明
参数 |
作用 |
srcBegin |
源字符串起始索引(包含) |
srcEnd |
源字符串结束索引(不包含) |
dst |
目标字符数组 |
dstBegin |
目标数组的起始写入位置 |
核心特性:
- 高效内存复制:直接操作字符数组,避免创建中间字符串对象
- 区间控制:复制
[srcBegin, srcEnd)
的字符到目标数组
- 原地修改:直接修改传入的
char[]
数组内容
3. 示例代码
StringBuffer sb = new StringBuffer("Hello, 世界!");
// 创建目标数组(长度需足够)
char[] buffer = new char[5];
// 复制索引[7,12)的字符 → "世界"
sb.getChars(7, 12, buffer, 0);
// 验证结果
System.out.println(Arrays.toString(buffer));
// 输出: [世, 界, \u0000, \u0000, \u0000] (未填充部分为默认值)
4. 使用技巧
- 部分字符串提取
// 提取后4字符
char[] last4 = new char[4];
sb.getChars(sb.length()-4, sb.length(), last4, 0);
- 组合多个子串
char[] combined = new char[10];
sb.getChars(0, 5, combined, 0); // 复制前5字符
sb.getChars(7, 9, combined, 5); // 后续字符从索引5开始
- 字符串预处理
char[] temp = new char[sb.length()];
sb.getChars(0, sb.length(), temp, 0);
Arrays.sort(temp); // 直接操作字符数组排序
5. 常见错误
- 索引越界
// 源索引超出范围
sb.getChars(0, 20, buffer, 0); // StringIndexOutOfBoundsException
// 目标索引超出数组长度
char[] small = new char[3];
sb.getChars(0, 5, small, 0); // IndexOutOfBoundsException
- 区间无效
// srcBegin > srcEnd
sb.getChars(5, 2, buffer, 0); // StringIndexOutOfBoundsException
- 空指针异常
char[] uninit = null;
sb.getChars(0, 3, uninit, 0); // NullPointerException
6. 注意事项
- 数组长度验证
目标数组必须满足:dstBegin + (srcEnd - srcBegin) <= dst.length
// 安全检查示例
int copyLen = srcEnd - srcBegin;
if (dstBegin + copyLen > dst.length) {
throw new IndexOutOfBoundsException("目标数组空间不足");
}
- 多字节字符处理
正确处理Unicode字符(如中文):
StringBuffer sb = new StringBuffer("A字");
char[] buf = new char[2];
sb.getChars(0, 3, buf, 0); // 正确:'A'(1字符)+ '字'(2字符)
- 目标数组内容覆盖
不会自动清空数组原有数据:
char[] data = {'A','B','C','D'};
sb.getChars(0, 2, data, 1);
// 结果: ['A', 'H', 'e', 'D'] (原'B','C'被覆盖)
7. 最佳实践与性能优化
- 复用字符数组(减少GC压力)
// 初始化大数组池
char[][] bufferPool = new char[10][1024];
int currentBuffer = 0;
void processString(StringBuffer sb) {
char[] buf = bufferPool[currentBuffer];
int len = sb.length();
if (buf.length < len) buf = new char[len];
sb.getChars(0, len, buf, 0);
// 处理逻辑...
bufferPool[currentBuffer] = buf;
currentBuffer = (currentBuffer + 1) % 10;
}
- 零拷贝处理
结合NIO进行高效I/O操作:
CharBuffer charBuffer = CharBuffer.allocate(1024);
sb.getChars(0, sb.length(), charBuffer.array(), 0);
FileChannel.write(ByteBuffer.wrap(charBuffer.array()));
- 批量操作优化
替代多次charAt()
调用:
// ❌ 低效方式
for (int i = 0; i < sb.length(); i++) {
char c = sb.charAt(i); // 每次调用都有边界检查
}
// ✅ 高效方式
char[] temp = new char[sb.length()];
sb.getChars(0, sb.length(), temp, 0);
for (char c : temp) { ... }
- 内存敏感场景优化
精确分配数组大小:
int start = 5, end = 15;
char[] exactSize = new char[end - start]; // 精确分配
sb.getChars(start, end, exactSize, 0);
总结
关键点 |
操作建议 |
核心价值 |
高性能字符复制,避免创建中间String对象 |
索引安全 |
始终校验:0 ≤ srcBegin ≤ srcEnd ≤ length() 且 dstBegin + len ≤ dst.length |
内存优化 |
复用char[]数组,精确分配空间 |
性能优势 |
替代循环charAt(),尤其适合大文本处理 |
特殊场景 |
与NIO/文件操作结合实现零拷贝 |