ArrayDeque 使用 Object[] 而非 E[] 是因 Java 禁止创建泛型数组,需靠类型擦除与强制转换保障类型安全;其循环逻辑依赖 head/tail 指针、2 的幂容量及位运算实现高效增删查。

Java 中 ArrayDeque 并不使用泛型数组,而是用 Object[] 数组配合类型擦除和强制转换来实现泛型语义——这是它能高效支持循环数组操作的关键前提。直接声明泛型数组(如 E[])在 Java 中是被禁止的,因为类型擦除后无法保证运行时类型安全。
为什么 ArrayDeque 不用 E[] 而用 Object[]
ArrayDeque 内部字段是 transient Object[] elements,而非 E[]。这是因为:
- Java 不允许在运行时创建具体泛型类型的数组(如
new E[16]),编译会报错 - 用
Object[]可绕过该限制,再通过显式类型转换(如(E) elements[i])完成读取,JVM 信任开发者已确保逻辑安全 - 写入时只存
Object,不触发类型检查;读取时强转,只要没混入错误类型,就不会出问题
循环数组中 head 和 tail 指针的计算逻辑
ArrayDeque 采用“首尾不重叠、tail 指向下一个空位”的设计,容量始终为 2 的幂(便于位运算优化)。关键指针关系如下:
- head:指向队首元素(非空时),初始为 0
- tail:指向队尾 后一个位置(即下一个插入位置),初始为 0
- 元素个数 =
(tail - head) & (elements.length - 1)(利用掩码替代取模,要求 length 是 2 的幂) - 下一个索引 =
(i + 1) & (elements.length - 1),等价于(i + 1) % elements.length,但更快
例如数组长度为 8(掩码为 7),当前 head=6, tail=1,则元素数 = (1 - 6) & 7 = (-5) & 7 = 3(补码运算下成立)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
addFirst / addLast 时的指针更新细节
所有添加操作都先检查是否需要扩容(tail == head 表示满),然后更新指针:
-
addLast(e):存入elements[tail],再执行tail = (tail + 1) & mask -
addFirst(e):先移动 head:head = (head - 1) & mask,再存入elements[head] - 减法取模用位与是因为
-1 & mask等价于mask(如-1 & 7 == 7),自然实现“绕回”
getFirst / getLast 的安全访问方式
读取不修改指针,但需防止空队列:
-
getFirst()→ 返回(E) elements[head],前提是head != tail -
getLast()→ 返回(E) elements[(tail - 1) & mask],因为 tail 指向空位 - 所有读操作都依赖
elements是Object[],否则无法绕过泛型数组限制
不复杂但容易忽略

















