本文参考"Thinking in java"的有关内容
1、源起
强化类间的逻辑关系或从属关系,比如将同类元素结合、将主类与工具类结合
2、优势
代码隐藏、与外围类通信、代码结构更加清晰
3、约束
内部类是紧紧依附于外部类对象的,也就是说没有一个已经实例化的外部类的对象,就无法实例化一个内部类对象,因此无法在外围类中定义static类型的内部类成员对象,但可以定义普通的内部类成员对象。典型误用:
package com.zjgtan.innerclasses;
public class TestBed {
public void f() {
System.out.println("f()");
}
public class Tester {
public void foo() {
TestBed t = new TestBed();
t.f();
}
}
public static Tester test = new Tester(); //这种语法是不行的,内部类紧紧的依附于外围类对象,实例化必须在外围类对象生成之后
}
因此除了在非静态方法里,其他任意位置创建某个内部类对象,必须指明这个对象的类型:OuterClassName.InnerClassName
4、链接外部类
内部类拥有对其外围类所有成员的访问权,内部类对象只能在于外围类的对象相关联时才能被创建
4.1 .this与.new
通过.this返回外围类对象的引用,这是容易理解的,this本身就是对象的一个成员。
[类对象].new,在外部构造内部类对象时的语法,也体现了绑定性
.this语法
public class DotThis {
void f() {
System.out.println("DotThis.f()");
}
public class Inner {
public DotThis outer() {
return DotThis.this; //返回当前外部类对象的引用
}
}
public Inner inner() {
return new Inner();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
DotThis dt = new DotThis();
DotThis.Inner dti = dt.inner(); //定义内部类对象,一定有相应的外部类对象
dti.outer().f(); //使用引用,调用成员函数
}
}
.new语法
public class DotNew {
public class Inner {
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
DotNew dn = new DotNew();
DotNew.Inner dni = dn.new Inner(); //.new语法,紧紧依附于外围类对象
}
}
5、匿名内部类
匿名内部类的重要应用,将返回值的生成与表示这个返回值的类的定义结合在一起
public class Parcel7 {
public Contents contents() {
return new Contents() { //内部类的定义
private int i = 11;
@Override
public int value() {
// TODO Auto-generated method stub
return i;
}
};
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Parcel7 p = new Parcel7();
Contents c = p.contents();
}
}
6、应用
6.1 工厂方法
鉴于工厂类和产品类逻辑上的从属关系,可以将它们组织到同一个类中
interface Service { //产品接口
void method1();
void method2();
}
interface ServiceFactory { //工厂接口
Service getService();
}
class Implementation1 implements Service {
private Implementation1() {
}
public void method1() {
System.out.println("Implementation1 method1");
}
public void method2() {
System.out.println("Implementation1 method2");
}
//构造工厂
public static ServiceFactory factory =
new ServiceFactory() { //将匿名内部类作为成员对象,工厂模式
@Override
public Service getService() {
// TODO Auto-generated method stub
return new Implementation1();
}
};
}
class Implementation2 implements Service {
private Implementation2() {
}
public void method1() {
System.out.println("Implementation2 method1");
}
public void method2() {
System.out.println("Implementation2 method2");
}
//构造工厂
public static ServiceFactory factory =
new ServiceFactory() {
@Override
public Service getService() {
// TODO Auto-generated method stub
return new Implementation2();
}
};
}
public class Factories {
public static void ServiceConsumer(ServiceFactory fact) { //客户端程序
Service s = fact.getService();
s.method1();
s.method2();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ServiceConsumer(Implementation1.factory);
ServiceConsumer(Implementation2.factory);
}
}
由上述实例可以看出,在客户端程序中,完全屏蔽了产品到底有多少种,将到底实例化哪个具体产品延迟到了运行期,实现了产品特性的模板化更新。
6.2迭代器模式
interface Selector { //迭代器接口,规定了迭代器的基本接口
boolean end();
Object current();
void next();
}
public class Sequence {
private Object[] items;
private int next = 0;
public Sequence(int size) { items = new Object[size]; }
public void add(Object x) {
if (next < items.length) {
items[next++] = x;
}
}
private class SequenceSelector implements Selector { //内部类的具体迭代器
private int i = 0;
public boolean end() { return i == items.length; }
public Object current() { return items[i]; }
public void next() {
if (i < items.length)
i++;
}
}
public Selector selector() { //返回迭代器
return new SequenceSelector();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Sequence sequence = new Sequence(10);
for (int i = 0; i < 10; i++) {
sequence.add(Integer.toString(i));
}
Selector selector = sequence.selector();
while (!selector.end()) {
System.out.print(selector.current() + " ");
selector.next();
}
}
}
将迭代器与具体类绑定,通过动态方法返回。
3、内部类与控制框架
模板方法、应用程序框架、命令设计模式