180
在Java 1.1 中,可将一个类定义置入另一个类定义中。这就叫作“内部类”。内部类对我们非常有用,因为利用它可对那些逻辑上相互联系的类进行分组,并可控制一个类在另一个类里的“可见性”。然而,我们必须认识到内部类与以前讲述的“合成”方法存在着根本的区别。
通常,对内部类的需要并不是特别明显的,至少不会立即感觉到自己需要使用内部类。在本章的末尾,介绍完内部类的所有语法之后,大家会发现一个特别的例子。通过它应该可以清晰地认识到内部类的好处。
创建内部类的过程是平淡无奇的:将类定义置入一个用于封装它的类内部(若执行这个程序遇到麻烦,请参见第3 章的3.1.2 小节“赋值”):
public class Parcel1 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
// Using inner classes looks just like
// using any other class, within Parcel1:
public void ship(String dest) {
Contents c = new Contents();
Destination d = new Destination(dest);
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tanzania");
}
} ///:~
当我们写代码时,有时候我们会想要把一些东西放在另外一些东西里面。就像你把玩具放进玩具箱里一样。在这个例子里,我们有一个叫做“Parcel1”的盒子,而盒子里面有两个小盒子,一个叫做“Contents”(内容),另一个叫做“Destination”(目的地)。
“Contents”盒子里装着一个数字。我们可以通过这个盒子里的一个特殊的门来看到这个数字是什么。
“Destination”盒子里装着一个标签,标签告诉我们这个盒子要送到哪里去。我们可以通过这个盒子里的一个特殊的门来看到标签上写了什么。
在我们的盒子里有一个特别的方法叫做“ship”(发货)。当我们想要把盒子送出去的时候,我们就会打开“Contents”盒子和“Destination”盒子,然后把它们准备好,最后将盒子寄出去。
在我们的故事结束时,我们创造了一个Parcel1盒子,并告诉它要送到坦桑尼亚。 Parcel1盒子就打开了“ship”门,把货物送出去了。
总之,这个故事告诉我们,内部类就像是一个盒子里的盒子,它们帮助我们把一些东西组织得井井有条,方便我们使用。
若在ship()内部使用,内部类的使用看起来和其他任何类都没什么分别。在这里,唯一明显的区别就是它的名字嵌套在 Parcel1 里面。但大家不久就会知道,这其实并非唯一的区别。
更典型的一种情况是,一个外部类拥有一个特殊的方法,它会返回指向一个内部类的句柄。就象下面这样:
public class Parcel2 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) {
label = whereTo;
}
String readLabel() { return label; }
}
public Destination to(String s) {
return new Destination(s);
}
public Contents cont() {
return new Contents();
}
public void ship(String dest) {
Contents c = cont();
Destination d = to(dest);
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tanzania");
Parcel2 q = new Parcel2();
// Defining handles to inner classes:
Parcel2.Contents c = q.cont();
Parcel2.Destination d = q.to("Borneo");
}
} ///:~
若想在除外部类非 static 方法内部之外的任何地方生成内部类的一个对象,必须将那个对象的类型设为“外部类名.内部类名”,就象 main()中展示的那样。
将内部类的对象类型设为“外部类名.内部类名”有几个好处:
1. **明确性和可读性:** 通过使用外部类名作为限定符,明确指出了内部类是外部类的一部分,这样在代码中就能清晰地看到它们之间的关系。
2. **避免命名冲突:** 如果在外部类和内部类中都定义了同名的类,使用外部类名作为限定符可以避免命名冲突。这样做可以确保代码的可维护性和可扩展性。
3. **代码组织和结构清晰:** 使用外部类名作为限定符可以使代码的组织结构更加清晰。当其他开发者阅读代码时,可以更容易地理解内部类是属于外部类的,而不是独立存在的。
4. **提高代码的可维护性:** 如果需要对内部类进行修改或者重构,使用外部类名作为限定符可以减少对其他部分代码的影响。这样做有助于降低代码的耦合度,提高代码的可维护性。
总之,将内部类的对象类型设为“外部类名.内部类名”可以增强代码的清晰度、可读性和可维护性,避免命名冲突,并有助于更好地组织和结构化代码。