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這個小妖精啊,也不是個省油的燈,想要學明白還差得遠啊~~~遠遠遠呀!!