数组工具类(ArrayUtil)
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.falsepattern.chunk.api.ArrayUtil |
| 修饰 | @ApiStatus.NonExtendable(不可被继承) |
| 方法 | 11 个静态 copyArray 重载(10 个基本/泛型数组 + 1 个 NibbleArray) |
| 源码行数 | 184 行,其中 11 个方法体各 6~12 行,全部形如同一段代码的复制 |
@SuppressWarnings("DuplicatedCode") 明确标注了这 11 个重载是有意复制的(Java 无法用泛型数组统一基本类型)。
统一的复制契约
前 10 个重载逐字相同的控制流:
if (src == null) return null; // null 透传
if (dst == null || src.length != dst.length)
return Arrays.copyOf(src, src.length); // 新分配
System.arraycopy(src, 0, dst, 0, src.length);
return dst; // 原地传输,复用 dst
每个方法都带同样的 @Contract:
@Contract(value = "null, _ -> null;" +
"!null, null -> new;", mutates = "param2")
⚠️ @Contract 与实现不完全一致:Arrays.copyOf 分支也在 src.length != dst.length 时触发(即 dst 非 null 但长度不同时),而契约只声明了 !null, null -> new。这是 Eclipse 契约表达能力有限,非源码错误。
返回 null 的唯一情形是 src == null——dst 为 null 或长度不符都返回新数组。因此调用方不能靠返回 null 判断"目标不可用",只能靠"源不可用"。
10 个基本类型 / 泛型重载
| # | 签名 |
|---|---|
| 1 | boolean[] copyArray(boolean[] src, boolean[] dst) |
| 2 | byte[] copyArray(byte[] src, byte[] dst) |
| 3 | char[] copyArray(char[] src, char[] dst) |
| 4 | short[] copyArray(short[] src, short[] dst) |
| 5 | int[] copyArray(int[] src, int[] dst) |
| 6 | long[] copyArray(long[] src, long[] dst) |
| 7 | float[] copyArray(float[] src, float[] dst) |
| 8 | double[] copyArray(double[] src, double[] dst) |
| 9 | <T> T[] copyArray(T[] src, T[] dst) |
(上表 9 项为基本类型与泛型重载;第 10 个基本类型重载之外,第 11 个是下节的 NibbleArray 特例。)
NibbleArray 特例
public static NibbleArray copyArray(NibbleArray srcArray, NibbleArray dstArray) {
if (srcArray == null) {
return null;
}
if (dstArray == null) {
return new NibbleArray(Arrays.copyOf(srcArray.data, srcArray.data.length), srcArray.depthBits);
}
dstArray.depthBits = srcArray.depthBits;
dstArray.depthBitsPlusFour = srcArray.depthBitsPlusFour;
dstArray.data = copyArray(srcArray.data, dstArray.data);
return dstArray;
}
与其他 10 个重载的三处差异:
- 新分配的分支用
new NibbleArray(byte[], int),而非Arrays.copyOf单独返回——因为NibbleArray是包装类,必须返回包装类型 - 额外同步两个标量字段
depthBits与depthBitsPlusFour(半字节深度,通常为 4) - 内部再调一次
copyArray(byte[], byte[])复用基本类型重载
⚠️ NibbleArray 的三个字段(data、depthBits、depthBitsPlusFour)都是非 public,直接赋值依赖 Access Transformer把它们公开化(见 Access Transformer)。没有 AT 的话这个方法无法编译。
⚠️ depthBitsPlusFour 被同步了,但 new NibbleArray(...) 分支只会从 depthBits 推算它——源码假定两者恒定关系(depthBits + 4)。
谁在用
全仓库 6 个调用点,全部在内置原版数据管理器的 clone 方法里(见 内置原版数据管理器):
| 调用点 | 数组类型 | 用途 |
|---|---|---|
BlockIDManager.cloneSubChunk |
byte[] × 2 |
LSB 数组 + MSB 数组 |
MetadataManager.cloneSubChunk |
NibbleArray |
metadata |
SkylightManager.cloneSubChunk |
NibbleArray |
skylight(有 hasNoSky 分支) |
BlocklightManager.cloneSubChunk |
NibbleArray |
blocklight |
LightingManager.cloneChunk |
int[] |
heightMap |
BiomeManager.cloneChunk |
byte[] |
biome 数组 |
即 ArrayUtil 的唯一用途是区块克隆时的数据搬运。经由 DataRegistry.cloneChunk / cloneSubChunk 两个 public 静态方法暴露给第三方(见 数据注册表)。
⚠️ BlocklightManager.cloneSubChunk 那一处把 ArrayUtil 的返回值赋给了 from 而非 to(源码笔误,详见 内置原版数据管理器)——ArrayUtil 本身行为正确,错在调用方。
char[] 与 float[] / double[] 三个重载在全仓库没有任何调用点,纯粹是为 API 完整性提供的。
相关条目
- API 接口 —
ArrayUtil在公开 API 里的定位 - 内置原版数据管理器 — 6 个调用点与
BlocklightManager的笔误 - Access Transformer —
NibbleArray字段公开化是本类能编译的前提