1. Java为什么不直接实现Iterator接口,而是实现Iterable?
这道题算是一道比较基础的题,面试官肯定也不是想让回答得多深入,只是考查对迭代器的了解程度,最好是看过源码,实际上迭代器的源码并不难。我们把注释折叠起来,Iterator接口的源码就是以下几行。
我们在面试中回答这个问题,可以从以下几个思路去回答。
- 分离职责:
Iterator接口定义了遍历集合元素的具体操作方法,如hasNext()、next()等,它负责提供遍历集合元素的能力,出现在Iterable接口的iterator()方法的返回值中。
Iterable接口包含方法iterator(),它的作用是为集合提供一个创建其迭代器实例的工厂方法。这意味着Iterable接口并不直接参与迭代过程,而是作为一个工厂角色,将迭代细节委托给具体的Iterator实现。
- 面向对象设计原则:
单一职责原则:Iterable接口专注于暴露一个创建迭代器的入口,而Iterator接口专注于定义迭代行为。这样,每个接口都专注于一项职责,提高了代码的模块化程度和可维护性。
依赖倒置原则:Iterable接口与Iterator接口的分离使得集合类(Iterable的实现)不需要直接依赖具体的迭代器实现细节,只需知道它能返回一个实现了Iterator接口的对象即可。这降低了耦合度,使得集合类的实现可以灵活地更换迭代器实现,有利于代码复用和扩展。
- 支持泛型与foreach语法:
Iterable接口在Java 5引入泛型后,定义为Iterable<T>,它明确指定了迭代器返回元素的类型。这使得集合类可以通过实现Iterable接口,为用户提供类型安全的迭代器,避免运行时类型转换错误。
自Java 5起,Java语言引入了for-each循环(也称为增强for循环),它可以直接作用于实现了Iterable接口的对象。通过实现Iterable而非Iterator,集合类能够无缝地支持这种简洁高效的遍历语法,提升了代码的可读性和易用性。
- API设计一致性与扩展性:
Iterable接口作为Java集合框架的顶层接口之一,是所有可迭代集合的通用接口。集合类统一实现Iterable接口,有利于保持API的一致性,使得客户端代码可以以统一的方式处理各种不同的集合类型。
若直接让集合类实现Iterator接口,将迭代器方法直接暴露在集合类上,可能会导致API设计混乱,也不利于后续扩展新的迭代器实现(如并行迭代器)。通过Iterable与Iterator的分离,可以更容易地为集合类添加新的迭代器实现,只需提供一个新的Iterator子类,而无需修改集合类本身。
这样的设计使得集合类与迭代器之间的耦合度降低,代码结构更加清晰,同时也为用户提供了一种更简洁、类型安全的遍历集合元素的方式。
如果大家需要视频版本的讲解,欢迎关注我的B站: