java 多态陷阱

照原来,先考考大家,在不运行的情况下说出下面程序的输出结果(请先注意这是关于多态的啊)

package acm;

//例一
class Test extends Main {
	private void write() {
		System.out.println("Test");
	}
}

public class Main {
	private void write() {
		System.out.println("Main");
	}

	public static void main(String[] args) {
		Main main = new Test();
		main.write();
	}
}

//我们所期望的是 输出Test,但由于private方法被自动认为是final方法。而且对导出的类是屏蔽的。因此
//在这种情况下,Test下的write就是一个全新的方法,Main中的方法在子类中方法不可见,因此也不能被重载
//只有非private 方法才可以被覆盖 。因此结果是:Main

//例二
class Super {
	public int field = 0;

	public int getField() {
		return field;
	}
}

class Sub extends Super {
	public int field = 1;

	public int getField() {
		return field;
	}

	public int getSuperField() {
		return super.field;
	}
}

public class Main {
	public static void main(String[] args) {
		Super sup = new Sub();
		System.out.println("sup.field= " + sup.field + ",sup.getField()="
				+ sup.getField());
		Sub sub = new Sub();
		System.out.println("sub.field= " + sub.field + ",sub.getField()="
				+ sub.getField() + ",sub.getSuperField()="
				+ sub.getSuperField());

	}
}

//当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的。
//在本例中,为Super.field和Sub.field分配了不同的存储空间。这样,Sub实际上包含两个称为field的域:
//它自己的和它从Super处得到的。结果:
//sup.field= 0,sup.getField()=1
//sub.field= 1,sub.getField()=1,sub.getSuperField()=0


//例三
class Glyph {
	void draw() {
		System.out.println("Glyph.draw()");
	}

	Glyph() {
		System.out.println("Glyph() before draw()");
		draw();
		System.out.println("Glyph() after draw()");
	}

}

class RoundGlyph extends Glyph {
	private int radius = 1;

	RoundGlyph(int r) {
		radius = r;
		System.out.println("RoundGlyph.RoundGlyph(),radius=" + radius);
	}

	void draw() {
		System.out.println("RoundGlyph.draw(),radius=" + radius);
	}
}

public class Main {
	public static void main(String[] args) {
		new RoundGlyph(5);
	}
}

//当Glyph 的构建器调用draw()时,radius 的值甚至不是默认的初始值1,而是 0。
//上一篇文章的所述初始化顺序是不全面的,实际过程是这样的: 
//(1) 在采取其他任何操作之前,为对象分配的存储空间初始化成二进制零。 
//(2) 调用基础类构建器。此时,被覆盖的draw()方法会得到调用(的确是在RoundGlyph构建器调用之前),
//此时会发现radius的值为 0,这是由于步骤(1)造成的。 
//(3) 按照原先声明的顺序调用成员初始化代码。 
//(4) 调用衍生类构建器的主体。 
//结果:
//Glyph() before draw()
// RoundGlyph.draw(),radius=0
// Glyph() after draw()
// RoundGlyph.RoundGlyph(),radius=5

以上均由近期读Thinking in Java所得


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值