AbstractList未重写方法是否保证依赖已重写方法实现?
问题场景与疑问
我自定义了一个继承自AbstractList的类MyList,仅重写了get和size方法:
static class MyList<E> extends AbstractList<E> { @Override public E get(int index) { return null; } @Override public int size() { return 0; } }
创建实例后,我可以直接调用未重写的iterator方法:
MyList<String> myList = new MyList<>(); myList.iterator();
理论上iterator会使用我重写的get方法,但我不确定这是否有官方保证——会不会后续iterator的实现被改成完全不依赖get方法?
再举个例子,若MyList重写了add方法:
@Override public boolean add(E e) { return super.add(e); // 具体实现无关紧要 }
调用myList.addAll(someOtherCollection)时,addAll可以通过循环调用add的方式实现,但也有可能像ArrayList那样改用不依赖循环的实现,这时候会不会不调用我重写的add方法?
我注意到iterator和addAll的官方文档有明确描述:
This implementation returns a straightforward implementation of the iterator interface, relying on the backing list's size(), get(int), and remove(int) methods.
以及:
This implementation iterates over the specified collection, and adds each object returned by the iterator to this collection, in turn.
那这些描述是否意味着这些方法的实现逻辑不会变更,属于官方规范?写完重读后我觉得答案似乎是“是”,但想确认清楚。
回答
答案确实是是。
Java官方对AbstractList中这些默认方法的文档描述,属于该类的规范承诺。所有遵循Java规范的实现(如Oracle JDK、OpenJDK等),都不会随意变更这些方法的依赖逻辑:
- 对于
iterator()方法,文档明确说明它依赖size()、get(int)和remove(int)方法,这是官方约定的行为,合规的Java实现必须保持这个依赖关系,不会改成不调用这些方法的实现。 - 对于
addAll()方法,文档明确说明它会遍历目标集合并逐个调用add()方法添加元素,因此只要你重写了add(),addAll()就一定会调用你的重写版本,不会改用绕过add()的实现方式。
这些文档内容不是单纯的实现细节说明,而是官方对方法行为的硬性约定,是子类可以放心依赖的规范内容。
内容的提问来源于stack exchange,提问作者Eugene

