继承中类以及成员变量初始化的讨论。
1.在講之前首先應該了解static、final、static final修飾符的含義,這里簡單介紹一下。
static:可以修飾變量、方法,被修飾的變量稱之為靜態變量,其初始化發生在其所在類第一次被裝載的時;被修飾的方法同樣。
final:可以修改變量、方法和類,被修飾的類或者方法是跟隨該類的實力對象的,在該對象被加載到內存當中(調用該類的構造方法時)被初始化,被修飾的變量不可變,方法不可被override(等同于被private修飾的方法),被修飾的類不可被集成,不能是抽象的,并且成員變量和方法都是final(不可變)類型的。
static final :可以修飾變量或者方法。修飾變量是代表著這個變量是靜態不可變的,初始化和static相同;被修飾的方法我沒有過多的了解,覺得只是為了做一個不可被修改的靜態類(感覺這樣做沒有意義)。
2.初始化順序
在任何情況發生以前,將父類和子類(可以是多個)被加載到內存當中,會默認把分配給父類和子類的內存空間初始化成二進制的零。
之后根據繼承的關系,從父類開始,依次執行初始化方法(調用構造器)進行實例化。
此時,類成員變量會“真正”的被初始化,按照你代碼編寫的樣子。
3。實例
父類
public class Glyph { private int a = 1; Glyph() { System.out.println("父類構造器"); draw();//調用子類中重寫的draw()方法 }void draw(){ System.out.println("Glyph.draw()"); } }子類:
public class RoundGlyph extends Glyph { private int radius = 1; //定義一個成員變量并賦初值 public RoundGlyph() { System.out.println("子類構造器"); }void draw(){ System.out.println("RoundGlyph.draw()="+radius); } }測試:
public class Test { public static void main(String[] args) { new RoundGlyph(); } }運行結果:
父類構造器 RoundGlyph.draw()=0 //調用子類中重寫的draw之后,打印子類的成員變量確實零。 子類構造器
4.結果分析
之所以運行的結果
RoundGlyph.draw()=0 而不是
RoundGlyph.draw()=1,是因為在父類構造器中調用子類中重寫的方法時,此時子類并沒有被“真正”實例化,現在還處于默認實例化的狀態,子類的成員變量radius默認初始化為0,所以打印結果為零。
5.static、final、static final修飾的成員變量時的情況。
修改子類代碼:---------------------static修飾時
public class RoundGlyph extends Glyph { private static int radius = 1; //初始化 static{ radius = 2;//初始化 } public RoundGlyph() { radius = 3;//初始化 System.out.println("子類構造器"); }void draw(){ System.out.println("RoundGlyph.draw()="+radius); } }?
運行結果為:
正如前面講到的,static會在類被裝載時就被初始化,也就是說,在子類RoundGlyph被裝載時變量radius就已經被初始化了,但為什么是2,重復的初始化不會報錯嗎? 答案是不會的,初始化時,只會根據你編寫的初始化順序進行,如果重復的對一個變量進行初始化了,后一個結果會覆蓋前一個結果,所以是2。
為什么不是3呢? 那是因為此時還子類RoundGlyph還沒有被“真正”的實例化,也就是說,在父類的構造方法中調用子類重寫的方法時,子類還沒有執行構造方法呢。
修改測試代碼:
運行結果:
父類構造器 RoundGlyph.draw()=2 子類構造器 RoundGlyph.draw()=3正如上面所說的,運行結果符合預期。
被final修飾時
子類代碼:
運行結果:
父類構造器 RoundGlyph.draw()=1 子類構造器運行結果為1,為什么又為一了呢?不應該是零嗎?
答案:確實應該是1 !因為radius此時的final類型的,如上面所說,final修飾的變量是不可變的,要么直接賦初值,要 ? ? ? ? ? ? ? ? 么在構造器中初始化,無論如何必須初始化!上面的測試是直接賦初值,所以為了保證被final修飾的變量是不可 ? ? ? ? ? ? ? ? 變的,而在構造器中又沒有初始化的變量,只能在默認初始化時對其進行初始化。
如果將上面子類的修改成:
public class RoundGlyph extends Glyph { private final int radius;public RoundGlyph() { radius = 1; //構造器初始化 System.out.println("子類構造器"); }void draw(){ System.out.println("RoundGlyph.draw()="+radius); } }運行結果:
父類構造器 RoundGlyph.draw()=0 子類構造器這說明如果沒對final修飾的變量賦值初始化時,就得在構造方法內對其進行初始化。運行結果和上面不同,也是好理解的了,因為是在構造器中初始化的,所以在沒有“真正”初始化之前,radius的值一直等于0。
用static final修飾的變量,跟static修飾時很像,只是初始化有些區別
子類代碼:
子類代碼2:(大同小異)
public class RoundGlyph extends Glyph { private static final int RADIUS ; static{ RADIUS = 1; } public RoundGlyph() { System.out.println("子類構造器"); }void draw(){ System.out.println("RoundGlyph.draw()="+RADIUS); } }運行結果:
父類構造器 RoundGlyph.draw()=1 子類構造器這個就不多贅述了,和static的一樣。只不過初始化時static final修飾的變量是不能在構造器中被初始化的,因為static是隸屬于類的,不隸屬于某一個具體的實例對象,static變量存儲在static storage(靜態存儲空間)中。
轉載于:https://www.cnblogs.com/acc1121/p/3156869.html
總結
以上是生活随笔為你收集整理的继承中类以及成员变量初始化的讨论。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 学习笔记
- 下一篇: poj 2524 Ubiquitous