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所得
摘自 一路向北
补充:软件开发 , Java ,