内部类是什么
-
类中定义的类(隐藏名字)
- 仅对包含该内部类的’外部类’可见
- 静态方法必须通过
外部类.内部类
的方式来调用 (是因为没有this
指针?) - 外部类能够访问内部类的一切对象,包括private
-
链接到外部类
- 内部类能访问所有制造它的外围对象的成员
- 引出设计模式之一:
迭代器模式
,将某个数组以类的形式包装起来,并设计诸如add(). next(), end()
等方法的形式对数组进行修改与访问的操作:
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){ 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(); } } }
- 在这段代码中,
selector
接口,而sequenceSelector
则是一个实现,它属于Sequence
的内部类,在Sequence
的main
方法中,首先创建了一个Sequence
对象,然后再创建了一个Selector
对象,利用Selector
接口所提供的方法来遍历数组,因此,这个内部类相当于一个迭代器。 - 为什么内部类自动拥有外部类的访问权限:当某个外部类的对象创建了一个内部类对象时,编译器会帮助内部类对象捕获一个指向外围类对象的引用。再访问外部类成员的时候,利用的就是这个引用。着也同时意味着,内部类是无法访问静态对象的。此外,内部类被规定一掉要能访问外部类对象,因此内部类是不允许被定义为static的。当然,在类中使用
static
关键字来定义一个类也是可以的,这种类被称为嵌套类(内部类也被称为非静态嵌套类)
-
在内部类中返回外部类引用
return outerclass.this
-
在外部类中创建内部类引用
outerclass.innerclass obj = outerclass.new innerclass()
- 换句话说内部类只能通过外部类调用
.new
方法创建,并且内部类对象不可能先于外部类对象的创建。
-
内部类与向上转型
- 书中令人费解的原话: 内部类向上转型为基类的时候,它是某个接口的实现,而内部类可以实现完全不可见与不可用(不可用是什么鬼?),它只是指向基类或者接口的引用,从而隐藏实现细节。
- 举例解释:
- 给定两个客户端程序员可见的接口,我们在调用引用的时候,在利用内部类进行实现的情况下,我们可能连实现这个接口的类的名字都不知道就可以创建引用。这样一来,这个实现类就不可能被继承与组合,从而无法扩展接口。
public interface Destination{ String readLabel();} public interface Contents{int value();} class Parcel4{ private class PContents implements Contents{ private int i = 11; pulbic int value(){return i;} } protected class PDestination implements Destination{ private String lable; private PDestination(String whereTo){ label = whereTo; } public String readLabel(){return label;} }// 内部类,接口Destination的实现 public Destination destination(String s){return new PDestination(s);} public Contents contents(){return new PContents();} } public class TestParcel{ public static void main(String[] args){ Parcel4 p = new Parcel4(); Contents c = p.contents(); Destination d = p.destinations("123"); } }
参考资料
- 《JAVA编程思想》