Java之内部类可以被覆盖吗详解(附源码)

前言


       如果创建了一个内部类,然后继承其外围类并重新定义此内部类时,会发生什么呢?也就是说,内部类可以被覆盖吗?这看起来似乎是个很有用的思想,但是“覆盖”内部类就好像它是外围类的一个方法,其实并不起什么作用:

示例源码1

package com.mufeng.thetenthchapter;

class Egg {
	private Yolk y;

	public Egg() {
		// TODO Auto-generated constructor stub
		System.out.println("new Egg()");
		y = new Yolk();
	}

	protected class Yolk {
		public Yolk() {
			// TODO Auto-generated constructor stub
			System.out.println("Egg.Yolk()");
		}
	}

}

public class BigEgg extends Egg {
	public class Yolk {
		public Yolk() {
			// TODO Auto-generated constructor stub
			System.out.println("BigEgg.Yolk()");
		}
	}

	public static void main(String[] args) {
		new BigEgg();
	}

}

输出结果1


new Egg()
Egg.Yolk()

源码解析1


       默认的构造器是编译器自动生成的,这里是调用基类的默认构造器。你可能认为既然创建了 BigEgg的对象,那么所使用的应该是“覆盖后”的 Yolk版本,但从输出中可以看到实际情况并不是这样的。
       这个例子说明,当继承了某个外围类的时候,内部类并没有发生什么特别神奇的变化。这两个内部类是完全独立的两个实体,各自在自己的命名空间内。当然,明确地继承某个内部类也是可以的:

示例源码2


package com.mufeng.thetenthchapter;

class Egg2 {
	private Yolk y = new Yolk();

	public Egg2() {
		// TODO Auto-generated constructor stub
		System.out.println("new Egg2()");
	}

	protected class Yolk {
		public Yolk() {
			// TODO Auto-generated constructor stub
			System.out.println("Egg2.Yolk()");
		}

		public void f() {
			System.out.println("Egg2.Yolk().f()");
		}
	}

	public void insertYolk(Yolk yy) {
		y = yy;
	}

	public void g() {
		y.f();
	}

}

public class BigEgg2 extends Egg2 {

	public BigEgg2() {
		// TODO Auto-generated constructor stub
		insertYolk(new Yolk());
	}

	public class Yolk extends Egg2.Yolk {
		public Yolk() {
			// TODO Auto-generated constructor stub
			System.out.println("BigEgg2.Yolk()");
		}

		public void f() {
			System.out.println("BigEgg2.Yolk().f()");
		}
	}

	public static void main(String[] args) {
		Egg2 e2 = new BigEgg2();
		e2.g();
	}

}

输出结果2


Egg2.Yolk()
new Egg2()
Egg2.Yolk()
BigEgg2.Yolk()
BigEgg2.Yolk().f()

源码解析2


      现在 BigEgg2.Yolk()通过 extends Egg2.Yolk()明确地继承了此内部类,并且覆盖了其中的方法。 insertYolk()方法允许 BigEgg2将它自己的 Yolk对象向上转型为 Egg2中的引用 y。所以当 g()调用 y.f()时,覆盖后的新版本的 f()被执行。第二次调用 Egg2.Yolk(),结果是 BigEgg2.Yolk的构造器调用了其基类的构造器。可以看到在调用 g()的时候,新版的 f()被调用了。






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值