在JAVA中,内部类似乎是一种名字隐藏和组织代码的一种形式,但内部类还有另一个最重要的用途:当生成一个内部类的对象时,此对象与制造它的外围对象之间构建了一种特殊的联系,内部类对象能够访问外围类对象的所有成员,而不需要任何条件。此外,内部类还拥有外围类所有元素的访问权。看如下一段代码:
package access;
interface Selector{
boolean end();
Object current();
void next();
}
public class Squence {
private Object[] items;
private int next = 0;
public Squence(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
Squence sequence = new Squence(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();
}
}
}
此程序的运行结果为:
在上述例子当中,Squence类是一个固定大小的Object数组,以类的形式包装了起来而已。add方法用来在序列末端加入新的Object。若想获取Squence中的每个对象,可以使用Selector接口。因为Selector是一个接口,所以别的类可以按它们自己的方式来实现这个接口,并且别的方法能以此接口作为参数来生成更加通用的代码。
SequenceSelector是一个内部类,但注意end方法、current方法、和next方法,这三个方法均调用了外围类的private访问权限的objects,所以说内部类可以无条件的访问外围类的任何成员及方法,无论访问权限是什么样的。
原理在于当某个外围类创建了一个内部类对象时,内部类对象必定会秘密捕捉一个指向那个外围类对象的引用,然后在我们访问外围类的成员时就是用这个引用来选择外围类的成员。内部类的对象只能在与其外围类的对象相关联的情况下才能被创建,构建内部类对象的时候,需要一个指向外围类对象的引用,如果编译器访问不到这个引用则会报错。
如果我们需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟“.this”,这样产生的引用自动具有正确的类型。比如如下一段代码:
package access;
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();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
DotThis dt = new DotThis();
DotThis.Inner dti = dt.inner();
dti.outer().f();
}
}
此程序运行结果为:
有时我们可能想要告知某些其他对象,去创建某个内部类的对象,要实现此目的,必须在new表达式中提供对其他外部类对象的引用,这时需要使用到“.new”,比如如下一段代码:
package access;
public class DotNew {
public class Inner{}
public static void main(String[] args) {
// TODO Auto-generated method stub
DotNew dn = new DotNew();
DotNew.Inner dni = dn.new Inner();
}
}
要想直接创建内部类对象,我们不能按照我们想象的方式去引用外部类名字DotNew,而是必须使用外部类的对象来创建内部类对象,在拥有外部类对象之前是无法创建内部类对象的,我们必须从外到内逐步创建,但如果创建的是嵌套类(静态内部类),则不需要对外部类对象的引用。
下面看一个关于“.new ”应用于Parcel的实例:
package access;
public class Parcel3 {
class Contents{
private int i = 11;
public int value(){
return i;
}
}
class Destination{
private String label;
Destination(String whereTo){
label = whereTo;
}
String readLabel(){
return label;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Parcel3 p = new Parcel3();
Parcel3.Contents c = p.new Contents();
Parcel3.Destination d = p.new Destination("Tasmania");
}
}