談?wù)凧ava中對(duì)象,類和this,super,static關(guān)鍵字的使用
Java對(duì)象究竟是什么
對(duì)象:對(duì)象是類的一個(gè)實(shí)例,有狀態(tài)和行為。
類:類是一個(gè)模板,它描述一類對(duì)象的行為和狀態(tài)。例如
人 是一個(gè)類
其狀態(tài)有:姓名、性別、身高、體重等
其行為:吃飯、睡覺、聊天、運(yùn)動(dòng)等
????public?class?Person?{ ????????/** ?????????*?狀態(tài)?or?屬性 ?????????*/ ????????String?name;//姓名 ????????String?sex;//性別 ????????int?height;//身高 ????????int?weight;//體重 ???????? ????????/** ?????????*?行為 ?????????*/ ????????public?void?sleep(){ ?????????System.out.println(this.name+"--"+?"睡覺"); ?????} ????????public?void?eat(){ ????????????System.out.println("吃飯"); ????????} ????????public?void?Dance(){ ????????????System.out.println("跳舞"); ????????} ????}
對(duì)象就是指具體的哪個(gè)人,比如"小張" 就是對(duì)象,可以通過new 來創(chuàng)建出來
public?static?void?main(String[]?args)?{ ????Person?zhang?=?new?Person(); ????zhang.name?=?"小張"; ????zhang.sex?="男"; ????zhang.height=180; ????zhang.weight=150; }
通過上面的例子,我們可以發(fā)現(xiàn) 面向?qū)ο筇岢鲆环N計(jì)算機(jī)世界里解決復(fù)雜軟件工程的方法論,拆解問題復(fù)雜度,從人類思維角度提出解決問題的步驟和方案。
因?yàn)槊嫦蜻^程讓計(jì)算機(jī)有步驟地順次做一件事情,是一種過程化的敘事思維,簡單明了。但是隨著軟件項(xiàng)目越來越龐大的時(shí)候,發(fā)現(xiàn)用面向過程語言開發(fā),軟件維護(hù)、軟件復(fù)用存在著巨大的困難。
創(chuàng)建對(duì)象的過程
一般來說,我們創(chuàng)建對(duì)象 可以通過new來 創(chuàng)建一個(gè),比如從上面的例子中這一句:
?Person?zhang?=?new?Person();
雖然我們寫的時(shí)候是簡單的一句,但是JVM內(nèi)部的實(shí)現(xiàn)過程卻是復(fù)雜的:
- 將硬盤上指定位置的Person.class文件加載進(jìn)內(nèi)存
- 執(zhí)行main方法時(shí),在棧內(nèi)存中開辟了main方法的空間(壓棧-進(jìn)棧),然后在main方法的棧區(qū)分配了一個(gè)變量zhang。
- 執(zhí)行new,在堆內(nèi)存中開辟一個(gè) 實(shí)體類的 空間,分配了一個(gè)內(nèi)存首地址值
- 調(diào)用該實(shí)體類對(duì)應(yīng)的構(gòu)造函數(shù),進(jìn)行初始化(如果沒有構(gòu)造函數(shù),Java會(huì)補(bǔ)上一個(gè)默認(rèn)構(gòu)造函數(shù))。
- 將實(shí)體類的 首地址賦值給zhang,變量zhang就引用了該實(shí)體。(指向了該對(duì)象)
JVM內(nèi)存分配情況
創(chuàng)建多個(gè)對(duì)象時(shí),內(nèi)存的變化
當(dāng)我們new 多個(gè)對(duì)象時(shí),屬性會(huì)另外開辟堆空間存放,而方法只有一份,不會(huì)額外消耗內(nèi)存
創(chuàng)建多個(gè)對(duì)象時(shí)-JVM內(nèi)存分配情況
我們接著來看一個(gè)例子:
public?static?void?main(String[]?args)?{ ??Person?ming?=?new?Person(); ????????ming.name?=?"ming"; ????????ming.sleep(); ????????Person?wang?=?new?Person(); ????????wang.name?=?"wang"; ????????wang.sleep(); }
運(yùn)行結(jié)果:
ming--睡覺
wang--睡覺
對(duì)象ming的 屬性在堆內(nèi)存,方法在方法區(qū)。當(dāng)我們?cè)谕ㄟ^Person類來 新增一個(gè)wang對(duì)象時(shí),棧內(nèi)存會(huì)有一個(gè)對(duì)象名稱wang,來指向在堆內(nèi)存中 新創(chuàng)建的另一個(gè)Person對(duì)象,屬性存放在堆內(nèi)存中。我們可以看出對(duì)象ming和對(duì)象wang 屬性 2者互不影響,相互獨(dú)立。
但是 對(duì)象ming和對(duì)象wang的方法區(qū) 是共用的。那為何2者屬性輸出結(jié)果不一樣呢?
其實(shí) 方法就像一套指令模板,誰都可以傳入數(shù)據(jù)交給它執(zhí)行,然后得到對(duì)應(yīng)執(zhí)行結(jié)果。
但是 JVM是如何確保 ming.sleep();
返回的結(jié)果是 小明在睡覺 而不是 小王在睡覺 或者其他情況?
Java的this其實(shí)就是解決這個(gè)問題的,接下來我們慢慢道來。
無處不在的this和super關(guān)鍵字
this 表示當(dāng)前對(duì)象的引用,可以理解為指向?qū)ο蟊旧淼囊粋€(gè)"指針",但是JAVA中是沒有指針這個(gè)概念的。
我們知道在C/C++中,指針是指向內(nèi)存中的地址,該地址就是存儲(chǔ)變量的值。該地址所存儲(chǔ)的變量值是"公有"的,此處的"公有"是對(duì)于擁有該地址的變量而言。它們隨時(shí)都可以訪問該地址的內(nèi)容,并且可對(duì)其進(jìn)行修改,一經(jīng)修改則所有指向該地址的變量值也將改變。
c++中也有結(jié)構(gòu)體、對(duì)象的概念,但是為什么他們不像java一樣有"封裝"的概念?
因?yàn)樵赾、c++中指針很強(qiáng)大,可以通過指針直接訪問操作內(nèi)存中的數(shù)據(jù)。而java沒有指針,這樣封裝就能極大地提升安全性。
雖然java中沒有指針的概念,但this("指針")無處不在.
從上面的例子 我們可以看出
????????public?void?sleep(){ ?????????System.out.println(this.name+"--"+?"睡覺"); ?????}
ming.sleep()和wang.sleep()語句調(diào)用的代碼是方法區(qū)同一個(gè)內(nèi)存,但是在JVM運(yùn)行過程中,可以根據(jù)由哪個(gè)對(duì)象發(fā)起對(duì)sleep()的調(diào)用,方法中所用到的成員變量數(shù)據(jù)就使用哪個(gè)對(duì)象的數(shù)據(jù)。這個(gè)本質(zhì)就像是方法傳參一樣,隱式傳遞this
this表示當(dāng)前對(duì)象的引用:
- this.屬性 區(qū)別成員變量和局部變量
- this.() 調(diào)用本類的某個(gè)方法
- this() 表示調(diào)用本類構(gòu)造方法,只能用在構(gòu)造方法的第一行語句。
- this關(guān)鍵字只能出現(xiàn)在非static修飾的代碼中
我們來看一個(gè)例子:
public?class?Main?{ ????public?static?void?main(String[]?args)?{ ????????Nanjing?nanjing?=?new?Nanjing(); ????????Beijing?beijing?=?new?Beijing(); ????} } public?class?Country?{ ?String?name; ????public?Country(){?//構(gòu)造器 ????????System.out.println(this.getClass().getName()); ????} } public?class?Beijing?extends?Country{ } public?class?Nanjing?extends?Country{ }
結(jié)果:
com.company.Nanjing
com.company.Beijing
子類Nanjing和Beijing 啥都沒干,但是卻通過父類Country的構(gòu)造器,得到子類的名字。
當(dāng)程序執(zhí)行new Nanjing()
語句去實(shí)例化子類時(shí),它會(huì)去隱式調(diào)用父類的構(gòu)造器,等同于:
public?class?Nanjing?extends?Country{ ?public?Nanjing()?{ ??super();//顯式?調(diào)用父類的構(gòu)造器 ?} }
這一過程中,會(huì)去隱式傳遞this,不然各個(gè)子類的名稱 不會(huì)顯示
我們?cè)賮砀脑煲幌翹anjing類的代碼:
public?class?Nanjing?extends?Country{ ????public?Nanjing()?{ ????????System.out.println("nanjing?自定義構(gòu)造器"); ????} }
結(jié)果:
com.company.Nanjing
nanjing 自定義構(gòu)造器
我們可以看出:如果 子類Nanjing自定義構(gòu)造器,會(huì)優(yōu)先調(diào)用父類的構(gòu)造器,再調(diào)用自己的構(gòu)造器
我們接著來看下 super關(guān)鍵字
super 表示自己超(父)類對(duì)象的引用,可以理解為是指向自己超(父)類對(duì)象的一個(gè)指針,而這個(gè)超類指的是離自己最近的一個(gè)父類。
super表示父類對(duì)象:
super.屬性 表示父類對(duì)象中的成員變量
super.方法()表示父類對(duì)象中定義的方法
super() 表示調(diào)用父類構(gòu)造方法
可以指定參數(shù),比如super("Nanjin");
任何一個(gè)構(gòu)造方法的第一行默認(rèn)是super();
可以寫上,如果未寫,會(huì)隱式調(diào)用super();
super()只能在構(gòu)造方法的第一行使用。
this()和super()都只能在構(gòu)造的第一行出現(xiàn),所以只能選擇其一。
寫了this()就不會(huì)隱式調(diào)用super()。
super 關(guān)鍵字在子類中顯式調(diào)用父類中被覆蓋的非靜態(tài)成員方法和成員變量
我們來看一個(gè)super調(diào)用父類方法的例子:
class?Father?{ ??void?message()?{ ????System.out.println("This?is?Father"); ??} } class?Son?extends?Father?{ ??void?message()?{ ????System.out.println("This?is?son"); ??} ??void?display()?{ ????message(); ????super.message(); ??} } class?Main?{ ??public?static?void?main(String?args[])?{ ????Son?s?=?new?Son(); ????s.display(); ??} }
結(jié)果:
This is son This is father
可以看出 super和this功能差不多,主要區(qū)別:this 指向當(dāng)前對(duì)象,super指向 離自己最近的一個(gè)父類,就不展開深入說了。
static關(guān)鍵字 為何如此特殊
Java中static`關(guān)鍵字主要用于內(nèi)存管理, 可以用來修飾變量或者方法。
由于JAVA面向?qū)ο筇幪幙梢?,在面向?qū)ο蟮乃季S下,方法與對(duì)象存在一種強(qiáng)耦合,簡單點(diǎn)來說就是 方法在沒有對(duì)象的情況下無法調(diào)用。
static關(guān)鍵字就是被設(shè)計(jì)來解決這個(gè)問題的。
我們來看一個(gè)例子:
public?class?Country?{ ????String?name?=?"china"; ???? ????public?void?show()?{ ????????System.out.println(name); ????} } public?static?void?main(String[]?args)?{ ????????Country?c1?=?new?Country(); ????????Country?c2?=?new?Country(); ????????c1.name?=?"china?new"; ????????c2.show(); ????}
結(jié)果:
china
如果用static修飾呢:
public?class?Country?{ ????static?String?name?=?"china"; ???? ????public?void?show()?{ ????????System.out.println(name); ????} }
結(jié)果:
china new
我們可以看出:
如果給一個(gè)屬性加上static,那么這個(gè)屬性不再屬于某一個(gè)對(duì)象了,而是是屬于類的,是所有對(duì)象共享的,共用同一個(gè)static屬性
可以通過類對(duì)象名.變量名 的方式訪問,比如:Country.nanme
當(dāng)程序進(jìn)行類加載時(shí),靜態(tài)方法隨著類加載而加載進(jìn)JVM中,此時(shí)并沒有對(duì)象實(shí)例化,優(yōu)先于對(duì)象的創(chuàng)建。static屬性在一個(gè)單獨(dú)的內(nèi)存區(qū),而不是在new出的對(duì)象內(nèi)存中
JVM內(nèi)存分布
另外一般來說 靜態(tài)方法不能訪問實(shí)例變量,其實(shí)是由于Java不會(huì)在調(diào)用靜態(tài)方法時(shí)傳遞this,沒有this就沒法處理差異化數(shù)據(jù)。
非static方法可以調(diào)用static方法,但static方法不能調(diào)用非static方法
以上就是談?wù)凧ava中對(duì)象,類和this,super,static關(guān)鍵字的使用的詳細(xì)內(nèi)容,更多關(guān)于Java 對(duì)象 類 關(guān)鍵字的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 舉例講解Java編程中this關(guān)鍵字與super關(guān)鍵字的用法
- java中this與super關(guān)鍵字的使用方法
- 關(guān)于java關(guān)鍵字this和super的區(qū)別和理解
- Java關(guān)鍵字詳解之final static this super的用法
- Java關(guān)鍵字this與super詳解用法
- Java中super和this關(guān)鍵字詳解
- Java中this和super關(guān)鍵字的使用詳解
- Java中的this、super、final關(guān)鍵字詳解
- JavaSE面試題之this與super關(guān)鍵字的區(qū)別詳解
相關(guān)文章
springBoot集成redis的key,value序列化的相關(guān)問題
這篇文章主要介紹了springBoot集成redis的key,value序列化的相關(guān)問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Java中Map與JSON數(shù)據(jù)之間的互相轉(zhuǎn)化
我們?cè)陂_發(fā)中難免和JSON打交道,這不小編最近遇到了,需要把一些信息轉(zhuǎn)成JSON字符串,下面這篇文章主要給大家介紹了關(guān)于Java中Map與JSON數(shù)據(jù)之間的互相轉(zhuǎn)化,需要的朋友可以參考下2023-04-04Windows安裝Maven并配置環(huán)境的詳細(xì)步驟
Maven是一個(gè)非常流行的構(gòu)建和項(xiàng)目管理工具,用于Java開發(fā),它提供了一個(gè)強(qiáng)大的依賴管理系統(tǒng)和一系列標(biāo)準(zhǔn)化的構(gòu)建生命周期,本文將指導(dǎo)您如何在Windows操作系統(tǒng)上安裝和配置Maven,需要的朋友可以參考下2023-05-05SpringBoot過濾器與攔截器深入分析實(shí)現(xiàn)方法
大家應(yīng)該都曉得實(shí)現(xiàn)過濾器需要實(shí)現(xiàn) javax.servlet.Filter 接口,而攔截器會(huì)在處理指定請(qǐng)求之前和之后進(jìn)行相關(guān)操作,配置攔截器需要兩步,本文通過實(shí)例代碼給大家介紹SpringBoot 過濾器和攔截器的相關(guān)知識(shí),感興趣的朋友一起看看吧2022-11-11Java任意長度byte數(shù)組轉(zhuǎn)換為int數(shù)組的方法
這篇文章主要給大家介紹了關(guān)于Java任意長度byte數(shù)組轉(zhuǎn)換為int數(shù)組的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07SpringBoot登錄驗(yàn)證token攔截器的實(shí)現(xiàn)
本文主要介紹了SpringBoot登錄驗(yàn)證token攔截器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07利用JSONObject.toJSONString()包含或排除指定的屬性
這篇文章主要介紹了利用JSONObject.toJSONString()包含或排除指定的屬性,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03