将一个类的定义放在另一个类的内部定义。
内部类与组合是完全不同的概念。
内部类是一种代码隐藏机制:将类置于其他类的内部。
内部类了解外围类,并能与之通信,用内部类写的的代码更加优雅清晰。
内部类分为成员内部类、静态嵌套类、方法内部类、匿名内部类。
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.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());
}
}