将一个类的定义放在另一个类的内部定义。
内部类与组合是完全不同的概念。
内部类是一种代码隐藏机制:将类置于其他类的内部。
内部类了解外围类,并能与之通信,用内部类写的的代码更加优雅清晰。
内部类分为成员内部类、静态嵌套类、方法内部类、匿名内部类。
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。
内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
要想直接创建内部类的对象,必须使用外部类的对象来创建该内部类对象。
要告知某些其他对象,去创建某个内部类的对象,必须在new表达式中提供对其他外部类对象的引用,需要使用.new语法
,使用new也解决了内部类名字的作用于问题,就像下面这样:
//1.必须通过外部类创建内部类对象 public class Outer { class Inner{ public Inner(){} } public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); System.out.println(outer.toString()); System.out.println(inner.toString()); }/** * Output: * thinkinjava4.demo_002.test.Outer@c17164 * thinkinjava4.demo_002.test.Outer$Inner@1fb8ee3 */ }
在拥有外部类对象之前是不可能创建内部类对象的。这是因为内部类对象会“连接”到创建它的外部类对象上。
但是,如果你创建的是嵌套类(静态内部类),那么它就不需要对外部类对象的引用。
上例的代码 Outer.Inner inner = outer.new Inner(); 在实例化的时候暴露了内部类的类名。将内部类换成private修饰,这样除了Outer,没有人能访问到内部类Inner,在Outer中添加一个public的公共方法获取内部类的实例。
private内部类给类的设计者提供了一种途径,通过这种方式可以完全阻止任何依赖于类型的编码,并却完全隐藏了实现的细节。就想下面这样:
public interface IContents { int value(); }
public interface IDestination { String readLabel(); }
public class Parcel { private class Contents implements IContents{ private int i = 11; @Override public int value() { return i; } } private class Destination implements IDestination{ private String label; public Destination(String whereTo) {label = whereTo;} @Override public String readLabel() { return label; } } //成员内部类,这里使用公共方法调用内部类的私有成员 public Contents getContents(){ return new Contents(); } public Destination getDestination(String whereTo){ return new Destination(whereTo); } }
public class ParcelTest { public static void main(String[] args) { Parcel p = new Parcel(); IContents c = p.getContents(); //IDestination d = p.new Destination("beijing"); IDestination d = p.getDestination("beijing"); } }
如果Destination是public的才可以使用注释部分的代码实例化。
由于不能访问任何新增加的、原本不属于公共接口的方法,所以扩展接口是没有价值的,这也给Java编译器提供了更高效代码的机会。
在内部类中,如果你需要生成对外部对象的引用,可以使用外部类的名字后面紧跟.this,这样产产生的引用自动的具有正确的类型,就像下面这样:
public class Outer { public class Inner{ public Outer getOuter(){ return Outer.this; } } public static void main(String[] args) { Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); System.out.println(inner.getOuter().getClass().getName()); } }