1
class Glyph {
2 void draw() {
3 System.out.println("Glyph.draw()");
4 }
5 Glyph() {
6 System.out.println("Glyph() before draw()");
7 draw();
8 System.out.println("Glyph() after draw()");
9 }
10 }
11
12 class RoundGlyph extends Glyph {
13 private int radius = 1;
14
15 RoundGlyph( int r) {
16 radius = r;
17 System.out.println("RoundGlyph.RoundGlyph(). radius = " + radius);
18 }
19
20 void draw() {
21 System.out.println("RoundGlyph.draw(). radius = " + radius);
22 }
23 }
24
25 public class Main {
26
27 public static void main(String[] args) {
28 new RoundGlyph(5);
29
30 }
31
32 }
2 void draw() {
3 System.out.println("Glyph.draw()");
4 }
5 Glyph() {
6 System.out.println("Glyph() before draw()");
7 draw();
8 System.out.println("Glyph() after draw()");
9 }
10 }
11
12 class RoundGlyph extends Glyph {
13 private int radius = 1;
14
15 RoundGlyph( int r) {
16 radius = r;
17 System.out.println("RoundGlyph.RoundGlyph(). radius = " + radius);
18 }
19
20 void draw() {
21 System.out.println("RoundGlyph.draw(). radius = " + radius);
22 }
23 }
24
25 public class Main {
26
27 public static void main(String[] args) {
28 new RoundGlyph(5);
29
30 }
31
32 }
以上这段代码的运行结果:
Glyph() before draw()
RoundGlyph.draw(). radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(). radius = 5
第一行:OK,调用子类的构造函数时先调用基类的构造函数,这个可以理解。
第二行:很明显,在基类的构造函数中调用的draw()方法被子类的draw()方法覆盖了。但是radius为什么是0呢?为什么!原因据说是这样的~
在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制0
也就是说,我调用draw()的时候,我们只是有了radius这个对象,然而程序还没进行到给这个对象赋值为1(见13行)??!?
第四行: 很好理解,前面做了那么多事之后,终于执行到子类的构造函数了。。这里面一定又发生了很多。。
然而,你以为这一切就这么简单吗?不。你试一下把基类的void draw()方法变成 private void draw()方法,那么有趣的事情发生了☞
运行结果变成了:
Glyph() before draw()
Glyph.draw()
Glyph() after draw()
RoundGlyph.RoundGlyph(). radius = 5
很好,对于这个问题,答案是:
只有非private方法才可以被覆盖。即,子类中,我们以为的覆盖private方法对子类来说是一个新的方法而非重载方法。因此在子类中,新方法最好不要与积累的private方法采取同一名字,以免误解。
那么如果把基类中的void draw()方法变成public void draw()方法呢?嗯,这时,程序会报错,需要把子类中的void draw()方法也变成public void draw()方法就OK了,效果和void draw()相同。
java这个小妖精啊,也不是个省油的灯,想要学明白还差得远啊~~~远远远呀!!