JAVA中内部类的继承和覆盖问题

在JAVA中,由于内部类的构建器必须连接到指向其外围类对象的引用,所以在继承内部类的时候会变得很复杂。问题在于指向外围类对象的秘密引用必须得到初始化,而在导出类中不再存在可连接的默认对象,我们必须使用特殊的语法来明确说明它们的关系:

enclosingClassReference.super()。

看如下一段代码:

package access;
class WithInner{
	class Inner{}
}
public class InheritInner extends WithInner.Inner{
	InheritInner(WithInner x){
		x.super();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		WithInner x = new WithInner();
		InheritInner i = new InheritInner(x);
	}

}
可以看到InheritInner只继承了内部类,并没有继承外围类,但若要生成一个构建器时,默认的构建器并不能完成此工作,不能只是传递一个指向外围类对象的引用,必须提供上述语法来确定一个关系。

如果我们创建了一个内部类,然后继承其外围类并重新定义内部类的时候会发生什么?看上去这和覆盖某种方法类似,但实际则不然,覆盖内部类就好像是外围类的一个方法,实际上并不起什么作用,看如下一段代码:

package access;
class Egg{
	private Yolk y;
	protected class Yolk{
		public Yolk(){
			System.out.println("Egg.Yolk()");
		}
	}
	public Egg(){
		System.out.println("New Egg()");
		y = new Yolk();
	}
}
public class BigEgg extends Egg{
	public class Yolk{
		public Yolk(){
			System.out.println("BigEgg.Yolk()");
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new BigEgg();
	}

}
此程序的运行结果为:


我们可能会与覆盖方法所混淆,认为既然创建了BigEgg的对象,那么所使用的应该是覆盖后的Yolk方法,但从输出来看并不是这样,当创建BigEgg对象时,构建器只是会先调用Egg的构建方法来初始化一个Egg,所以所有的输出均来自于Egg,而我们在BigEgg中并没有调用任何的方法来操纵BigEgg中的Yolk方法,只有当出现调用时,才会发生输出,改动一下此代码:

package access;
class Egg{
	private Yolk y;
	protected class Yolk{
		public Yolk(){
			System.out.println("Egg.Yolk()");
		}
	}
	public Egg(){
		System.out.println("New Egg()");
		y = new Yolk();
	}
}
public class BigEgg extends Egg{
	private Yolk x;
	public class Yolk{
		public Yolk(){
			System.out.println("BigEgg.Yolk()");
		}
	}
	public BigEgg(){
		System.out.println("New BigEgg()");
		x = new Yolk();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new BigEgg();
	}

}
此程序的输出结果为:


可以看到只有在实际发生调用时候才会进行输出,这与方法覆盖有着本质的区别。
当我们继承了某个外围类的时候,内部类并没有发生什么特别神奇的变化,内部类是完全独立的实体,各自在自己的命名空间内,看如下一段代码:

package access;
class Egg2{
	protected class Yolk{
		public Yolk(){
			System.out.println("Egg2.Yolk()");
		}
		public void f(){
			System.out.println("Egg2.Yolk().f()");
		}
	}
	private Yolk y = new Yolk();
	public Egg2(){
		System.out.println("New Egg2()");
	}
	public void insertYolk(Yolk yy){
		y = yy;
	}
	public void g(){
		y.f();
	}
}
public class BigEgg2 extends Egg2{
	public class Yolk extends Egg2.Yolk{
		public Yolk(){
			System.out.println("BigEgg2.Yolk()");
		}
		public void f(){
			System.out.println("BigEgg2.Yolk.f()");
		}
	}
	public BigEgg2(){
		insertYolk(new Yolk());
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Egg2 e2 = new BigEgg2();
		e2.g();
	}

}
此程序的输出结果为:


可以看到的是BigEgg2.Yolk通过继承Egg2.Yolk明确继承了内部类并覆盖了其中的方法。

insertYolk方法现在允许BigEgg2将自己的Yolk对象上转型为Egg2中的引用y,所以当g()调用y.f()时,覆盖后的f()被执行。

第二次调用Egg2.Yolk,结果是BigEgg2.Yolk的构建器调用了基类的构建器。

输出结果的前两行是在创建BigEgg2对象的时候首先对基类进行初始化的结果,第三行是在创建BigEgg2时调用基类的insertYolk方法时重新对y进行构建的结果,最后两行是在用上转型的Egg2引用操作对象BigEgg2时调用继承过来的内部类方法的结果。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值