71. Java 嵌套类 - 内部类的使用方式
内部类示例讲解
在本示例中,我们使用一个简单的整数数组来说明内部类的使用方式。示例目标如下:
- 创建一个整数数组,数组内容为从 0 开始连续递增的数字。
- 只打印数组中偶数索引(即 0、2、4……)上的元素,并按顺序输出。
1. 主要结构
外部类 DataStructure
- 定义了一个固定大小的整数数组
arrayOfInts,在构造方法中自动填充连续整数(例如 0, 1, 2, …)。 - 提供了一个
printEven()方法,用于打印偶数索引上的元素。
内部类 EvenIterator
- 是
DataStructure的一个成员内部类,实现了自定义的迭代器接口DataStructureIterator(它扩展自Iterator<Integer>)。 - 内部类专门遍历偶数索引,逻辑简单:每次
next()方法返回当前偶数索引的值后,将索引增加 2,跳到下一个偶数位置。
主方法 main()
- 在
main()方法中创建DataStructure的实例,并调用printEven()方法,从而打印出偶数索引处的元素。
2. 代码实现
public class DataStructure {
// 定义数组大小
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
// 构造方法:填充数组,元素依次为 0, 1, 2, 3, ..., SIZE-1
public DataStructure() {
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
// 打印偶数索引上的元素
public void printEven() {
// 使用内部类 EvenIterator 作为迭代器
DataStructureIterator iterator = this.new EvenIterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
}
// 自定义迭代器接口,扩展自 java.util.Iterator<Integer>
interface DataStructureIterator extends java.util.Iterator<Integer> {}
// 内部类:只迭代偶数索引的元素
private class EvenIterator implements DataStructureIterator {
private int nextIndex = 0; // 从索引 0 开始
// 检查是否还有下一个偶数索引元素
public boolean hasNext() {
return (nextIndex <= SIZE - 1);
}
// 返回当前偶数索引元素,并将索引跳跃 2 位
public Integer next() {
Integer retValue = Integer.valueOf(arrayOfInts[nextIndex]);
nextIndex += 2;
return retValue;
}
}
// 主方法:演示内部类的使用
public static void main(String[] args) {
DataStructure ds = new DataStructure();
ds.printEven();
}
}
3. 运行结果
0 2 4 6 8 10 12 14
说明程序只打印了数组中偶数索引处的元素。
-
内部类优势:
- 由于
EvenIterator是DataStructure的内部类,它可以直接访问外部类的arrayOfInts数组,而不需要额外的 getter 方法。
- 由于
-
内部类在这种场景下起到了“外部类助手”的作用,使得代码逻辑更清晰,职责分明。
4. 补充说明:局部类与匿名类
除了成员内部类外,Java 还有两种特殊的内部类:
- 局部类:在方法内部定义,仅在该方法内可见,适合封装仅局部使用的逻辑。
- 匿名类:没有类名的内部类,通常用于快速实现接口,比如 GUI 事件监听器等场景。
这些特殊内部类与成员内部类具有相同的特性,都可以直接访问外部作用域中的变量,但它们的使用场景更局限于方法或表达式内部。
5. 总结
-
内部类的作用:
- 内部类能够直接访问外部类的成员变量,不需要额外的访问器,从而实现更紧密的封装和逻辑关联。
-
本例中的
EvenIterator:- 通过内部类实现只迭代偶数索引,简化了遍历逻辑,提高了代码可读性。
-
其他内部类类型:
- 局部类与匿名类适用于方法内部的临时需求,常用于事件处理等场景。
希望这个示例能帮助大家更好地理解内部类的概念和实际应用。