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