先上代码:
class Outer
{
public class Inner
{
public String getInnerClassName()
{
return Inner.this.getClass().toString(); //'Inner' can be omitted here
}
public String getOuterClassName()
{
return Outer.this.getClass().toString(); //'Outer' CANNOT be omitted here
}
}
public Inner createInner()
{
return new Inner(); //'return this.new Inner();' is OK here
}
}
public class InnerTest
{
public static void main(String[] args)
{
Outer o = new Outer();
Outer.Inner i1 = o.new Inner();
Outer.Inner i2 = o.createInner();
System.out.println(i1.getOuterClassName());
System.out.println(i2.getInnerClassName());
}
}
//output:
/*
class Outer
class Outer$Inner
*/
1. .new
内部类对象是不能直接创建的。必须先创建一个外部类对象,再由这个外部类对象来创建内部类对象。这样处理可能是为了体现内部类对象是依存外部类对象存在的,即内部类对象不能脱离外部类对象而存在。一个外部类对象可以创建多个内部类对象(类似Process与Thread的关系)。创建方法有2种:
- OuterClassObj.new InnerClass():即使用.new和内部类构造器,如上面代码中的:
Outer.Inner i1 = o.new Inner();
- OuterClassObj.InnerClassConstructorProxy():即使用在外部类中定义的内部类构造器的代理方法,如上面代码中的:
Outer.Inner i2 = o.createInner();
上面2种方法其实是等价的。
这里注意,内部类的声明类型必须是Outer.Inner,编译出的文件为Outer$Inner.class。
2. .this
其实可以把this当作class的一个static field,就算不用内部类,也可以照样用class.this形式,如上面代码中的:
public String getInnerClassName()
{
return Inner.this.getClass().toString(); //'Inner' can be omitted here
}
不过鉴于内部类和外部类的特殊关系,内部类必须能够访问其创建者,所以在内部类中可以使用Outer.this来指向创建这个内部类对象的外部类对象。如: [code="java"][/code]
public String getOuterClassName()
{
return Outer.this.getClass().toString(); //'Outer' CANNOT be omitted here
}
p.s. 总结一点,.this与class连用(类似staitc,class.this),.new与reference连用(obj.new)。
3. 对外部类的field和function的访问
就如同我们在一般类的方法或是constructor中省略this一样,内部类的方法也是如此,只是内部类中省略的是this(i.e. Inner.this)和Outer.this这2个this。所以看上去在内部类的方法中可以直接访问外部类的field/function,而且无论是哪种访问权限的field/function都可以访问,其实是因为内部类方法中可以通过Outer.this链接到外部类,由外部类来访问外部类的field/function,自然是可以不考虑访问权限了。
如果内部类和外部类有同名的field/function,单纯使用SameFieldName或是SameFunctionName()会被优先识别为内部类的field/function,如果想要用外部类的field/function,必须用Outer.this来指定。
如果你手中只有内部类对象,比如i1、i2,这样是无法直接访问外部类的field/function的,因为外部类的field/function并不属于内部类,类似i1.OuterField或是i2.OuterFunction()是无法通过编译的。所以i1、i2想要访问外部类的field/function只能间接通过内部类的方法。
总之,简单的说,内部类对象要想访问外部类对象的field或是function的话,必须要先获得创建自己的外部类对象的引用。