内部类(一)
内部类就是: 将一个类的定义放在另一个类的定义内部。
一、创建内部类:
public class Parcel { 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){ Parcel p = new Parcel(); p.ship("puji"); Parcel q = new Parcel(); // 在外部类的非静态方法之外的任意位置创建内部类的对象,需要指明外部类 Parcel.Contents c = q.contents(); Parcel.Destination d = q.to("tailand"); } }
创建内部类就是在外部类里定义内部类即可,就是讲一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。
注意:
- 通常要声明一个方法,该方法返回内部类的引用,这样在定义内部类的对象时,调用该方法进行初始化;
- 如果是在静态方法里创建内部类的对象引用,需要指明外部类:外部类名.内部类名;
二、链接到外部类
内部类可以访问外部类的所有成员(域和方法),就像自己拥有的一样,无需任何特殊条件!
三、使用.this和.new
- 如果生成外部类对象的引用,可以使用外部类名.this的方式。这样产生的引用自动具有正确的类型。
public class DotThis{ void f(){System.out.println("a");} public class Inner{ public DotThis outer() { //下面的句子实际是代替了 return new DotThis(); return DotThis.this; } } public Inner inner(){return new Inner();} public static void main(String[] args){ DotThis dt = new DotThis(); DotThis.Inner dti = dt.inner(); dti.outer().f(); } }
第一个例子中已经创建过内部类的对象引用,是在外部类里新电话已一个方法,返回内部类引用;然后创建时通过外部类对象调用该方法。
- 要想直接创建内部类对象,必须使用外部类的对象来创建该内部类的对象,使用外部类对象名.new;
public class DotNew { public class Inner {} public static void main(String[] args){ DotNew dn = new DotNew(); DotNew.Inner dni = dn.new Inner(); } }
四、内部类和向上转型
使某个内部类实现某个接口,并在外部类的其他位置定义一个返回内部类对象引用的方法,此方法的返回类型定义为接口类型;此时将内部类声明为private或protected。
这样做的目的是:此内部类——某个接口的实现——能够完全不可见,并且不可用。所得到的只是指向基类或接口的引用,很方便地隐藏实现细节。
eg.
首先定义两个内部类要实现的接口:
public interface Destination { String readLabel(); } public interface Contents { int value(); }
然后,在外部类里定义两个内部类,访问权限为private/protected,实现这两个接口;然后定义两个方法,可以返回类型为接口,方法体内返回的是内部类引用,此时是向上转型。这样,客户端程序员就无法访问到内部类的具体实现,他只能得到这两个接口。
class Paracel { private class PContents implements Contents { //override... } protected class PDestination implements Destination { //override... } public Destination destination(String s){ return new PDestination(s); } public Contents contents(){ return new PContents(); } }
最后,可以看到就不能用.new方法创建内部类对象,因为声明为private类型了;所以只能用公共的接口和外部类的方法来创建,完全不可见内部类的任何信息。
class TestParcel{ public static void main(String[] args){ Parcel p = new Parcel(); Contents c = p.contents(); Destination d = p.destination("puji"); //Illegal--cant access private class : // Parcel.Pcontents pc = p.new PContents(); } }
详见<Thinking in java> P190 : 10.1-4 内部类