任何人都可以向我解释 Arrays.copyOfRange(byte[], int, int))奇怪行为背后的逻辑吗?我可以用简单的例子来说明我的意思:
byte[] bytes = new byte[] {1, 1, 1};
Arrays.copyOfRange(bytes, 3, 4); // Returns single element (0) array
Arrays.copyOfRange(bytes, 4, 5); // Throws ArrayIndexOutOfBoundsException
在这两种情况下,我都会在数组边界之外复制范围 (即start >= array.length
),因此错误的条件对我来说至少是奇怪的(如果是from < 0
或{{ 1}})。我认为应该是:from > original.length
或from < 0
。也许我错过了什么?
答案 0 :(得分:4)
The JavaDoc指出了关于它所期望的论点的三点:
一:
[来自] 必须介于零和 original.length 之间,包括
二:
[ to ] 必须大于或等于来自
三:
[ to ]可能大于 original.length
对于Arrays.copyOfRange(bytes, 3, 4)
的情况,一,二,三是真的,这意味着它们是有效的。
对于Arrays.copyOfRange(bytes, 4, 5)
的情况,只有两个和三个为真,这意味着它们无效。
预期的行为?是。
不直观的行为?有点。
如果您的问题是秘密地“为什么是这样设计的?”除了代码作者,没有人可以告诉你答案。
答案 1 :(得分:0)
看看copyOfRange的工作原理:
public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
最重要的部分是:
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
所以当你调用Arrays.copyOfRange(bytes,3,4)时; System.arraycopy的最后一个参数“length - 要复制的数组元素的数量”是0. arraycopy的调用看起来像System.arraycopy(original,from,copy,0,0);
答案 2 :(得分:0)
查看Arrays.copyOfRange(byte[] original, int from, int to)
的来源 public static byte[] copyOfRange(byte[] original, int from, int to) {
1 int newLength = to - from;
2 if (newLength < 0)
3 throw new IllegalArgumentException(from + " > " + to);
4 byte[] copy = new byte[newLength];
5 System.arraycopy(original, from, copy, 0,
6 Math.min(original.length - from, newLength));
7 return copy;
}
1
1
,所有元素均为0
在第6行,要复制的元素的长度计算为零,因为
// Math.min(original.length - from, newLength));
Math.min(3 - 3, 1)); --> returns zero
System.arraycopy
根本不会将任何内容复制到数组copy
如果from
为bytes.length + 1
,则length
为负(bytes.length - from)。
要演示的小代码
public class ArrayCopy {
public static void main(String[] args) {
byte[] bytes = new byte[]{11, 12, 13};
int from = 3;
int to = 4;
copyOfRange(bytes, from, to);
from = 2;
to = 3;
copyOfRange(bytes, from, to);
from = 4;
to = 5;
copyOfRange(bytes, from, to);
}
static void copyOfRange(byte[] bytes, int from, int to) {
System.out.printf("%ncopyOfRange(bytes: %s from: %d to: %d)%n",
Arrays.toString(bytes),
from,
to
);
// line 1
int newLength = to - from;
System.out.println("int newLength = " + newLength);
// line 2
if (newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
// line 4
byte[] copy = new byte[newLength];
// to show that in the suspicious case System.arrayCopy does nothing
copy[0] = 42;
System.out.println("byte[] copy = " + Arrays.toString(copy));
int length = bytes.length - from;
System.out.println("int length = " + length);
int minLenght = Math.min(length, newLength);
System.out.println("int minLenght = " + minLenght);
// line 5
System.arraycopy(bytes, from, copy, 0, minLenght);
System.out.println("byte[] copy = " + Arrays.toString(copy));
}
}
输出
copyOfRange(bytes: [11, 12, 13] from: 3 to: 4)
int newLength = 1
byte[] copy = [42]
int length = 0
int minLenght = 0
byte[] copy = [42]
copyOfRange(bytes: [11, 12, 13] from: 2 to: 3)
int newLength = 1
byte[] copy = [42]
int length = 1
int minLenght = 1
byte[] copy = [13]
copyOfRange(bytes: [11, 12, 13] from: 4 to: 5)
int newLength = 1
byte[] copy = [42]
int length = -1
int minLenght = -1
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
答案 3 :(得分:0)
这意味着您可以使用此方法创建任意长度的新“空”数组,就像您在 Model MPG Cylinders Engine Disp Horsepower Weight Accelerate Year Origin
0 amc ambassador dpl 15.0 8 390 190 3850 8.5 70 American
1 amc gremlin 21.0 6 199 90 2648 15.0 70 American
2 amc hornet 18.0 6 199 97 2774 15.5 70 American
3 amc rebel sst 16.0 8 304 150 3433 12.0 70 American
4 buick estate wagon (sw) 14.0 8 455 225 3086 10.0 70 American
5 buick skylark 320 15.0 8 350 165 3693 11.5 70 American
8 volkswagen 1131 deluxe sedan 26.0 4 97 46 1835 20.5 70 European
12 volkswagen model 111 27.0 4 97 60 1834 19.0 71 European
情况中所描述的那样。
// Returns single element (0) array
方法存在的主要目的是因为它“动态”创建新数组。当然,这个新阵列可能比源阵列更大。
该行为是documented功能。
范围的最终索引(to),必须大于或等于from,可能大于original.length ,在这种情况下 '\ u000'放置在索引较大的副本的所有元素中 大于或等于original.length - 来自。返回的长度 数组将来自 - 。
为什么这样实施?假设你要调用它:
Arrays.copyOfRange
它将创建数组[1,0,0,0],并且原始数组中不存在的所有元素将按当前类型的默认文字初始化。 但如果您想指定byte[] bytes = new byte[] {1, 1, 1};
byte[] newBytes = Arrays.copyOfRange(bytes, 2, 6); // Returns array length 6 - 2 = 4
更大但不等于from
(文档不鼓励),则在调用此bytes.length
时会导致ArrayIndexOutOfBoundsException
因为System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
将小于original.length - from
。
技术上说如果你使用这样的指示:
0
假设您只想创建一个大小为int n = 4;
Arrays.copyOfRange(bytes, bytes.length, bytes.length + n);
的新空数组。换句话说,您正在创建一个新数组并从源数组中复制任何内容。