1.什么是内部类?
可以将一个类的定义放在另一个类的定义内部,这就是内部类。
如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须像在main()
方法中那样,具体的指明这个对象的类型:OuterClassName.InnerClassName
当生成一个内部类的时候,它能访问其他外为对象的所有成员,此外,内部类还拥有其他外围类的所有元素的访问权。
这是如何做到的呢?
当某个外围类创建一个内部类对象的时候,此内部类对象必定秘密的捕获一个指向那个外围来对象的应用。然后,在你访问次外围类的成员时,就是那个引用来选择外围类的成员。这部分工作有编译器来帮我们处理。
如果你要生成对外部类对象的引用,可以使用外部类的名字后面跟上远点和this。例如: return OuterClassNeme.this;
当你想要告知某些对象,去创建其某个内部类的对象,必须在new表达式中提供对其他外部类对象的引用,这需要使用.new 语法
OuterClass oc = new OuterClass();
OuterClass.InnerClass ic = oc.new InnerClass();
从类的设计角度看,private内部类给类的设计者提供了一种途径,通过这样的方式可以完全阻止任何依赖于类型的编码,并且完全隐藏了实现的细节。因为打当内部类向上转型成其基类,尤其是转型成一个接口的时候,内部类阻止了了客户端在使用过程中将对象向下转型,因为不知道其名字。
2.匿名内部类
定义一个方法将返回值的生成和返回值的类的定义结合在一起
public class Parcel7b{
class MyContents implements Contents{
private int i = 11;
public int value() {return i;}
}
public Contents contents(){return new MyContents;}
public static void main(String[] args){
Parcel7b p = new Parcel7();
Contents c = p.Contents();
}
}
上述内部类的声明方式如果转化成匿名内部类就是下面这个样子.
public class Parcel7{
public Contests contents(){
return new Contents(){
private int i = 11;
public int value(){return i;
}
};
}
public static void main(String[] args){
Parcel7 p = new Parcel7();
Contents c = p.Contents();
}
}
看起来就是这个样子的:在你想创建一个对象的时候,插入了这个对象对应的类定义方式。
匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以扩展接口,但是不能两者兼备,而且如果是实现接口,也只能实现一个接口
这样有什么好处呢?可以用来简化工厂模式的实现。P187&&P199
将工厂具名类以匿名内部类的形式放在产品类的内部,这样皆可以省去创建工厂具名类的功夫,只需要单一的工厂对象就可以啦。
在Android中,我们定义线程的方式就是匿名内部类:
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
3.静态内部类(嵌套类)
如果不需要内部类对象与其外围类对象有联系,那么可以将内部类声明为static,通常称之为嵌套类。嵌套类意味着:
1.要创建嵌套类对象,并不需要其外围类对象。2.不能从嵌套类对象中访问非静态的外围类对象
3.普通内部类不能有static数据和static字段,也不能包含嵌套类,而嵌套类可以包含所有这些东西
4.为什么要使用内部类
使用内部类最吸引人的原因是:
每个内部类都能独立的继承一个(接口)的实现,所以无论外围类是否已经集成了某个(接口)的实现,对于内部类没有影响。这种属性对于多重继承来说,无疑是一种神器。
不只对于接口,假设你想继承两个或者三个类,外部类只能继承一个,剩下的而就可以交给内部类来实现,因为内部类可以持有外部类的引用,所以可以使用继承到的方法来操作外部类的数据,也就是说实现了多重继承。在《Thinking in Java》中举了一个通过内部类实现继承迭代器的方式。见P192
最后放一个简单的例子:
abstract class InnerAny{
abstract void out();
}
public class Outer{
private int i = 0;
class Inner{
int i = 8;
public void out(){
System.out.println(this.i);
System.out.println(Outer.this.i);
}
}
static class InnerStaic{
static int i = 1;
public InnerStaic(Outer p){
i = p.i;
}
}
public InnerAny ia(){
return new InnerAny(){
public void out(){
Outer.this.i++;
System.out.println(Outer.this.i);
}
};
}
public static void main(String[] args){
Outer p = new Outer();
System.out.println(p.i);
//普通内部类
Outer.Inner in = p.new Inner();
in.out();
p.i++;
//静态内部类
InnerStaic is = new InnerStaic(p);
System.out.println(is.i);
p.i++;
System.out.println(Outer.InnerStaic.i);
in.out();
//匿名内部类
InnerAny ia = p.ia();
ia.out();
}
}
输出是:0 8 0 1 1 8 2 3