先说明一个类名指定方式的问题。开门见山上代码!(以注释为重,多余代码忽略)
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 contents() { return new Contents(); } public void ship(String dest) {//在非静态方法中只需要写出内部类名便可指定其类型 Contents c = contents(); Destination d = to(dest); System.out.println(d.readLabel()); } public static void main(String[] args) { Parcel2 p = new Parcel2(); p.ship("Tasmania"); Parcel2 q = new Parcel2(); Parcel2.Contents c = q.contents(); Parcel2.Destination d = q.to("Borneo"); } }
注意:在Parcel2类内指定内部类只需用内部类名。在Parcel2外要定义内部类类型的话,必须用 [外部类名].[内部类名] 的方式。
《Thinking in Java》上说,内部类不只是一种名字隐藏和组织代码的模式。
下面就来介绍一下内部类一些其他的特性。
1、内部类拥有其外围类的所有元素的访问权。即使该类是多层的内部类,他对外面的每一层都有相同的访问权限。(这是因为在创建内部类的一个对象时候,自生成了一个外部类对象与该对象的引用,当在内部类中访问外部类成员时使用的就是该引用。而这个过程是不可见的。)。
2、在内部类中使用 [外部类名].this 的方式获得外部类的引用。
public class DotThis { void f() { System.out.println("DotThis.f()"); } public class Inner { public DotThis outer() { return DotThis.this; // 这里使用this的话是指向Inner的。 } } public Inner inner() { return new Inner(); } public static void main(String[] args) { DotThis dt = new DotThis(); DotThis.Inner dti = dt.inner(); dti.outer().f(); } }
3、创建内部类对象
public class DotNew { public class Inner {} public static void main(String[] args) { DotNew dn = new DotNew(); DotNew.Inner dni = dn.new Inner(); } }
只能通过 [外部类引用].new [内部类名]()的方式来新建内部类对象。
4、还可以在方法中声明类,不过该类的作用范围只在该方法内。甚至在if、while等语句内也可以定义类。
public int value() { if(true){ class aa{ } } while(true){ class aa{ } } return i; }
5、接口内的内部类:默认是public和static。它们两者只是简单的嵌套,内部类还可以实现它外部的接口。
public interface ClassInInterface {
void howdy();
class Test implements ClassInInterface {
public void howdy() {
System.out.println("Howdy!");
}
public static void main(String[] args) {
new Test().howdy();
}
}
}
6、内部类的继承
class WithInner { class Inner {} } public class InheritInner extends WithInner.Inner { InheritInner(WithInner wi) { wi.super(); } public static void main(String[] args) { WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); } }
继承了内部类Inner的InheritInner类的构造函数必须入代码所示:传入外围类对象,并且调用外围类的构造函数。
7、内部类的覆盖
class Egg { private Yolk y; protected class Yolk { public Yolk() { System.out.println("Egg.Yolk()"); } } public Egg() { System.out.println("New Egg()"); y = new Yolk(); } } public class BigEgg extends Egg { public class Yolk { public Yolk() { System.out.println("BigEgg.Yolk()"); } } public static void main(String[] args) { new BigEgg(); } } /* Output: New Egg() Egg.Yolk()
BigEgg继承了Egg类,以我们以往的经验,BigEgg中的Yolk内部类会覆盖Egg类中的Yolk类,但是实际并不是如此:两个Yolk类是两个完全独立的实体,各自在各自的命名空间。可以这么说,除了类名相同外这两个类没什么联系。
但下面的这种情况可以达到我们覆盖内部类的要求
class Egg2 { protected class Yolk { public Yolk() { System.out.println("Egg2.Yolk()"); }//3-->Egg2.Yolk() 6--->Egg2.Yolk() public void f() { System.out.println("Egg2.Yolk.f()");} } public Egg2() { System.out.println("New Egg2()"); }//4--->New Egg2() private Yolk y = new Yolk();//2 public void insertYolk(Yolk yy) { y = yy; }//7 public void g() { y.f(); }//9 } public class BigEgg2 extends Egg2 { public class Yolk extends Egg2.Yolk { public Yolk() { System.out.println("BigEgg2.Yolk()"); }//7--->BigEgg2.Yolk() public void f() { System.out.println("BigEgg2.Yolk.f()"); }//10--->BigEgg2.Yolk.f() } public BigEgg2() { insertYolk(new Yolk()); }//5 public static void main(String[] args) { Egg2 e2 = new BigEgg2();//1 e2.g();//8 } } /* Output: Egg2.Yolk() New Egg2() Egg2.Yolk() BigEgg2.Yolk() BigEgg2.Yolk.f()
通过指定内部类继承的类可以达到我们的期望。如BigEgg2中明确地指出了Yolk继承自Egg.Yolk类。代码中数字给出了运行过程。
内部类的一个重要作用:使JAVA“多继承”成为可能。
8、对于类来说,只有内部类能被private关键字修饰。