如何在 Java 中使用 String.copyValueOf() 从字符数组的特定位置生成新的子串
String.copyValueOf()方法用于从字符数组生成字符串,其重载方法可指定起始位置和复制长度,而非结束索引。参数需满足非负且起始位置加长度不超过数组边界,否则会抛出异常。该方法不支持类似子串截取的起始-结束索引语义,也不接受负数参数。
String.copyValueOf() 不支持 substring 式截取,其重载方法 copyValueOf(char[], int offset, int count) 中 offset 为起始索引、count 为复制长度(非结束索引),需满足 offset≥0、count≥0 且 offset+count≤数组长度,否则抛 ArrayIndexOutOfBoundsException。

String.copyValueOf() 不能直接截取子串,它只复制整个数组或指定长度
很多开发者初次接触 copyValueOf 时,容易产生一个误解:以为它能像 substring 那样,指定一个起始位置和一个结束位置来“切”出子串。实际上,这个理解是有偏差的。String.copyValueOf(char[]) 和它的重载方法 String.copyValueOf(char[], int, int),其参数设计是「起始索引」加上「要复制的字符长度」,而不是「起始索引」加「结束索引」。换句话说,它并不支持类似 Python 切片 [start:end] 那样的语义。
一个典型的错误场景是这样的:调用 String.copyValueOf(chars, 3, 5),本意是想获取数组下标从 3 到 7 的字符,结果却抛出了 IndexOutOfBoundsException。问题出在哪?就在于第三个参数 5 被解释为“复制 5 个字符”,而不是“复制到下标 5”。
- 正确理解参数:第二个参数是起始位置(
offset),第三个参数是复制的长度(count)。 - 必须满足的前提条件:
offset >= 0 && count >= 0 && offset + count <= chars.length。 - 单参数版本:如果只传入一个字符数组,其效果等同于
copyValueOf(chars, 0, chars.length),即复制整个数组。
想从中间开始截取?必须用三参数重载 + 手动算长度
那么,如果确实需要从数组中间截取一部分来构建字符串,该如何操作呢?关键在于手动计算出需要的长度。
举个例子,假设有一个字符数组 char[] data = {'a','b','c','d','e','f'},现在想取出子串 "de"(对应下标 3 和 4)。正确的做法是明确告诉方法:从下标 3 开始,取 2 个字符。
char[] data = {'a','b','c','d','e','f'};
String s = String.copyValueOf(data, 3, 2); // 结果 → "de"
这里需要特别注意:copyValueOf(data, 3, 4) 的意思是尝试从下标3开始取4个字符(即下标3,4,5,6),这会导致越界;而 copyValueOf(data, 3, 5) 则是尝试取5个字符(下标3到7),同样会失败,因为数组总共只有6个元素。
立即学习“Ja va免费学习笔记(深入)”;
- 若已知起始下标
start和结束下标end(通常遵循左闭右开原则),那么需要复制的长度应为end - start。 - 务必在调用前进行校验:
if (start >= 0 && end <= data.length && start < end)。 - 不要与
Arrays.copyOfRange(char[], from, to)混淆,后者返回的是一个新的char[]数组,而不是String对象。
和 new String(char[], int, int) 对比:行为一致,但语义更清晰
在功能上,String.copyValueOf(char[], int, int) 与使用构造函数 new String(char[], int, int) 是完全等效的,它们底层最终调用的是相同的字符串构造逻辑。区别主要体现在语义层面:前者是一个静态工厂方法,其名称“copyValueOf”更清晰地表达了“复制数组值”的意图;后者是构造函数,有时可能会让开发者误以为它与原始数组共享了底层存储(实际上,在 Ja va 7u6 之后,所有字符串构造都会进行深拷贝,不会共享数组)。
- 推荐优先使用
copyValueOf:代码意图更明确,也能避免对无参构造函数等不相关重载的误用。 - 性能无差异:两者在时间复杂度上都是 O(n),都需要复制指定范围的字符。
- 安全性一致:无论使用哪种方式,生成的字符串都与原字符数组脱钩,后续对原数组的修改不会影响已创建的字符串。
真正容易被忽略的坑:空数组、null 和编码无关性
copyValueOf 方法只处理纯粹的 Unicode 字符(UTF-16 编码单元),不涉及任何字符编码转换。但在实际使用中,一些边界情况常常被忽略:
- 传入
null数组:会直接抛出NullPointerException,不会进行静默处理或返回空字符串。 - 传入空数组:
new char[0]是合法的,copyValueOf(new char[0])会返回一个空的字符串""。 - 复制长度为零:例如
copyValueOf(data, 5, 0),即使不复制任何字符,也会返回空字符串""。但请注意,此时仍会检查offset的有效性,如果offset > array.length,即使count为 0,也会抛出ArrayIndexOutOfBoundsException。 - 没有反向操作:不支持使用负数作为
offset或count来实现“从末尾往前取”,传入负数会直接抛出IllegalArgumentException。


































