第十章:内部类:可以将一个类的定义放在另一个类的定义内部
- 内部类作用:
- 内部类可以起到隐藏和组织代码的模式
- 内部类可以无条件的访问外部类的任何成员(c++的嵌套类只是丹村的名字隐藏机制)
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; @Override public boolean end() { return i == items.length; } @Override public Object current() { return items[i]; } @Override public void next() { if(i < items.length){ i++; } } } public Selector selector(){ return new SequenceSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for (int i = 0; i < 10; i++) { sequence.add(i); } Selector selector = sequence.selector(); while(!selector.end()){ System.out.println(selector.current()+" "); selector.next(); } } }
- 如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须使用OuterClassName.InterClassName
- .this/.new
- 如果你需要生成对外部类对象的引用,可以使用OuterClassName.this
- 用外部类创建某个内部类对象使用OuterClassObj.new
- 可以在一个方法里面或者在任意的作用域内定义内部类,但是都是和其他类一起编译
- 匿名内部类:
- 如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,,那么编译器会要求其参数引用为final
- 对于匿名类而言,实例初始化的实际效果就是构造器
- 匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以实现接口,但是两者不能兼具,而且如果实现接口,也只能实现一个接口
- 匿名工厂实现:
interface Service{ void method1(); void method2(); } interface ServiceFactory{ Service getService(); } class Implementation1 implements Service{ private Implementation1() { } @Override public void method1() { System.out.println("Implementation1 method1"); } @Override public void method2() { System.out.println("Implementation1 method2"); } public static ServiceFactory factory = new ServiceFactory() { @Override public Service getService() { return new Implementation1(); } }; } class Implementation2 implements Service{ private Implementation2() { // TODO Auto-generated constructor stub } @Override public void method1() { // TODO Auto-generated method stub System.out.println("Implementation2 method1"); } @Override public void method2() { // TODO Auto-generated method stub 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 consumer(ServiceFactory sf){ Service s = sf.getService(); s.method1(); s.method2(); } @Test public void test(){ consumer(Implementation1.factory); consumer(Implementation2.factory); } }
- 如果不需要内部类对象与外围类对象之间有联系,可以将内部类声明为static,通常称为嵌套类(与C++嵌套类的区别是,Java中可以访问私有成员)
- 要创建嵌套类的对象,并不需要其外围类的对象
- 不能从嵌套类的对象中访问非静态的外围类对象
- 普通的内部类不能有static数据和static字段,也不能包含嵌套类
- 嵌套类可以作为接口的一部分,接口的任何类都会被自动加上public static
- 为什么需要内部类
- 每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响
- 内部类允许继承多个非接口类型
- 当继承了某个外部类的时候,内部类并没有发生什么特别神起的变化,这两个内部类是完全独立的两个实体,各自在自己的命名空间内