????01-面向?qū)ο?Static關(guān)鍵字)
? ? ? ? 我們發(fā)現(xiàn)一個問題式撼,這兩個對象中有相同的屬性值,每個對象的內(nèi)容都是一樣的求厕,這樣會比較耗費內(nèi)存空間著隆,我們能不能把相同的部分取出來放在一個地方,誰要用就拿過去用呀癣,沒有必要每個對象都存一份美浦。
? ? ? ? 這個時候就需要給這個變量前面加上static。
? ? ? ? 靜態(tài):static项栏。
? ? ? ? 用法:是一個修飾符浦辨,用于修飾成員(成員變量,成員函數(shù))沼沈。
? ? ? ? 當(dāng)成員被靜態(tài)修飾后流酬,就多了一個調(diào)用方式,除了可以被對象調(diào)用外庆冕,還可以直接被類名調(diào)用康吵。調(diào)用方式為:類名.靜態(tài)成員。
? ? ? ? 被靜態(tài)修飾后访递,country就不再在堆內(nèi)存當(dāng)中了晦嵌。
? ? ? ? 靜態(tài)修飾的變量是被對象所共享的。
? ? ? ? 類名調(diào)用好方便拷姿!那干脆把所有屬性都靜態(tài)好啦惭载,都可以類名調(diào)用!比如姓名什么的响巢。
? ? ? ? 懊杼稀?姓名踪古?emmm...好像有點問題誒含长。
? ? ? ? 國籍大家都是一樣的,都是中國人伏穆,但是姓名卻是各自不同的拘泞。
? ? ? ? 我們要明白,事物當(dāng)中哪些屬性是共享的枕扫,哪些是特有的陪腌。特有的一定要跟著對象來存儲。
? ? ? ? static特點:
? ? ? ? 1,隨著類的加載而加載诗鸭。
? ? ? ? ? ? ? ? 也就是說染簇,靜態(tài)會隨著類的消失而消失。說明它的生命周期最長强岸。
? ? ? ? ? ? ? ? 因此锻弓,也不建議把所有有的沒的的變量都定義成靜態(tài),這樣即使對象沒了请唱,這些變量還在內(nèi)存中弥咪,是對內(nèi)存的一種消耗过蹂。所以定義靜態(tài)之前一定要想好十绑,這個東西是不是需要被所有對象所共享?是酷勺,定義靜態(tài)本橙。不是,就別定義靜態(tài)啦脆诉!
? ? ? ? 2甚亭,優(yōu)先于對象存在。
? ? ? ? ? ? ? ? 明確一點:靜態(tài)是先存在击胜,對象是后存在亏狰。
? ? ? ? ? ? ? ? 即使沒有對象存在,這個靜態(tài)成員也已經(jīng)存在了偶摔。(沒有對象存在的時候暇唾,也無法通過對象來調(diào)用這個成員變量,就只能通過類來調(diào)用辰斋,所以就有第四條所說的策州,可以直接被類名調(diào)用)
? ? ? ? 3,被所有對象所共享宫仗。
? ? ? ? 4够挂,可以直接被類名調(diào)用。
? ? ? ? 實例變量和類變量的區(qū)別:
? ? ? ? 1藕夫,存放位置孽糖。
? ? ? ? ? ? ? ? 類變量隨著類的加載而存在于方法區(qū)中。
? ? ? ? ? ? ? ? 實例變量隨著對象的建立而存在于堆內(nèi)存中毅贮。
? ? ? ? 2办悟,生命周期。
? ? ? ? ? ? ? ? 類變量聲明周期最長嫩码,隨著類的消失而消失誉尖。
? ? ? ? ? ? ? ? 實例變量生命周期隨著對象的消失而消失。
? ? ? ? 靜態(tài)使用注意事項:
? ? ? ? 1铸题,靜態(tài)方法只能訪問靜態(tài)成員铡恕。成員包括方法和變量琢感。(如果還沒有建立對象,這個時候就沒辦法訪問非靜態(tài)成員啦探熔,因為它們還不存在呢)
? ? ? ? ? ? ? 非靜態(tài)方法既可以訪問靜態(tài)也可以訪問非靜態(tài)驹针。
? ? ? ? 2,靜態(tài)方法中不可以定義this诀艰,super關(guān)鍵字柬甥。
? ? ? ? ? ? ? 因為靜態(tài)優(yōu)先于對象存在。所以靜態(tài)方法中不可以出現(xiàn)this其垄。
? ? ? ? 3苛蒲,主函數(shù)是靜態(tài)的。
? ? ? ? 靜態(tài)有利有弊:
? ? ? ? 利:對對象的共享數(shù)據(jù)進行單獨空間的存儲绿满,節(jié)省空間臂外。沒有必要每一個對象中都存儲一份。
? ? ? ? 可以直接被類名調(diào)用喇颁。
? ? ? ? 弊:生命周期過長漏健。
? ? ? ? 訪問出現(xiàn)局限性。(靜態(tài)雖好橘霎,只能訪問靜態(tài))
? ? ? ? 介紹一個新的內(nèi)存空間蔫浆,方法區(qū):
? ? ? ? 靜態(tài)變量既不在堆中也不在棧中,而是在方法區(qū)中姐叁。方法區(qū)中同時也存放著該類的各種方法~(細心的我發(fā)現(xiàn)了之前堆內(nèi)存中都木有畫方法瓦盛,嘻嘻)
????02-面向?qū)ο?main函數(shù))
? ? ? ? 為什么主函數(shù)是靜態(tài)的呢?
? ? ? ? 我們這節(jié)來講一講七蜘。
? ? ? ? public static void main(String[] args)
? ? ? ? 主函數(shù):是一個特殊的函數(shù)谭溉。作為程序的入口,可以被jvm調(diào)用橡卤。
? ? ? ? 主函數(shù)的定義:
? ? ? ? public:代表著該函數(shù)訪問權(quán)限是最大的。
? ? ? ? static:代表主函數(shù)隨著類的加載就已經(jīng)存在了柜与。
? ? ? ? void:主函數(shù)沒有具體的返回值嵌灰。
? ? ? ? main:不是關(guān)鍵字,但是是一個特殊的單詞沽瞭,可以被jvm識別迁匠。
? ? ? ? (String[] args):函數(shù)的參數(shù),參數(shù)類型是一個數(shù)組,該數(shù)組中的元素是字符串城丧。也就是說延曙,是存儲字符串類型的數(shù)組。
? ? ? ? 主函數(shù)是固定格式的:jvm識別亡哄。 ? ? ? ?
? ? ? ? args的原型是arguments枝缔,剛開始是這樣寫的,因為比較長蚊惯,所以后來簡寫成args愿卸。
? ? ? ? ?那么,虛擬機到底傳入了什么呢截型?
? ? ? ? 因此,jvm在調(diào)用主函數(shù)時菠劝,傳入的是new String[0];
? ? ? ? 能不能打印角標(biāo)為0的元素呢赊舶?
? ? ? ? 越界啦园骆!
? ? ? ? 剛剛那個0的意思是長度是0锄码,是有0個元素,而不是里面存的東西是0重窟。而0角標(biāo)代表的是第一個元素。
? ? ? ? javac啟動了編譯器厅翔,java啟動了底層虛擬機。要使用哪個類戈次,就將這個類的類名作為參數(shù)傳入虛擬機。傳進去的同時悬秉,它會調(diào)用這個類的main方法,我們試著在后面再加一些主函數(shù)的參數(shù):emmm...haha hehe heihei武氓。
? ? ? ? 虛擬機做了一件事剂桥,自動的將類名后面所跟的數(shù)據(jù)美尸,存入了數(shù)組當(dāng)中。
? ? ? ? 不信看一看~
? ? ? ? 不信再看一看~
? ? ? ? 再玩點更有意思的:
? ? ? ? 這兩個類是獨立的,虛擬機可以執(zhí)行類1主函數(shù)惶岭,也可以執(zhí)行類2主函數(shù)。我們用虛擬機執(zhí)行其中一個類的主函數(shù)噪矛,這個的主函數(shù)也可以調(diào)用另一個類的主函數(shù)。
????03-面向?qū)ο?靜態(tài)什么時候使用)
? ? ? ? 什么時候使用靜態(tài)缩滨?
? ? ? ? 要從兩方面下手:
? ? ? ? 因為靜態(tài)修飾的內(nèi)容有成員變量和函數(shù)。
? ? ? ? 什么時候定義靜態(tài)變量(類變量)呢侧巨?
? ? ? ? 當(dāng)對象中出現(xiàn)共享數(shù)據(jù)時,該數(shù)據(jù)被靜態(tài)所修飾坦仍。(比如姓名就不是共享數(shù)據(jù),他們只是共享屬性,都有這個屬性,但每個人的姓名值是不一樣的傀履。)
? ? ? ? 對象中的特有數(shù)據(jù)要定義成非靜態(tài)存在于堆內(nèi)存中。
? ? ? ? 什么時候定義靜態(tài)函數(shù)呢梆暮?
? ? ? ? 當(dāng)功能內(nèi)部沒有訪問到非靜態(tài)數(shù)據(jù)(對象的特有數(shù)據(jù))偿荷,那么該功能可以定義成靜態(tài)的。
? ? ? ? 比如:
? ? ? ? show方法改成靜態(tài)后直接類名調(diào)用就OK啦:
? ? 04-面向?qū)ο?靜態(tài)的應(yīng)用-工具類)
? ? ? ? 這個例子中,將獲取最大值的功能封裝在一個函數(shù)中,提高了代碼的復(fù)用性逛拱。
? ? ? ? 但是,不只這個類會用到獲取最大值的功能曹步,其他類也會用到。我們就可以把這個功能抽取出來筹麸,封裝在一個類中,這個類想什么時候用就什么時候用。
? ? ? ? 靜態(tài)的應(yīng)用? ? ? ??
? ? ? ? 每一個應(yīng)用程序中都有共性的功能,可以將這些功能進行抽取参歹,獨立封裝缸血,以便復(fù)用。
? ? ? ? 第一次編譯后赤赊,當(dāng)前目錄中會產(chǎn)生一個ArrayTool.java文件哄孤,第二次就不用再編譯工具類啦。
? ? ? ? 如果把這個.java文件刪掉晨逝,編譯就會出錯。
? ? ? ? 下一個問題:我們有必要建立這個對象嗎趁窃?
? ? ? ? 不用仔細想叔汁,就知道,這個對象另假,并沒有用到ArrayTool類中的特有屬性和特有功能己莺。
? ? ? ? 總結(jié)一下:
? ? ? ? 雖然可以通過建立ArrayTool的對象使用這些工具方法,對數(shù)組進行操作胜蛉。
? ? ? ? 但發(fā)現(xiàn)了問題:
? ? ? ? 1,對象是用于封裝數(shù)據(jù)的,可是ArrayTool對象并未封裝特有數(shù)據(jù)嘲碱。
? ? ? ? 2,操作數(shù)組的每一個方法都沒有用到ArrayTool對象中的特有數(shù)據(jù)离咐。
? ? ? ? 這時就考慮,讓程序更嚴(yán)謹(jǐn)术陶,是不需要對象的。
? ? ? ? 可以將ArrayTool中的方法都定義成static的塘匣。直接通過類名調(diào)用即可。
? ? ? ? 直接這樣調(diào)用就OK啦:
? ? ? ? 將方法都靜態(tài)后笤闯,可以方便于使用,但是該類還是可以被其他程序建立對象的。
? ? ? ? 為了更為嚴(yán)謹(jǐn)捐韩,強制讓該類不能建立對象。
? ? ? ? 可以通過將構(gòu)造函數(shù)私有化來完成仅政。
? ? ? ? 到這里,這個工具類的功能基本完善啦辫封。
? ? ? ? 還有一個細節(jié)上的小問題:交換的這個功能是工具類中其他方法需要調(diào)用到的,并不對外提供使用,也將它私有化~
? ? ? ? 總之拓劝,能隱藏起來的就隱藏起來,不需要暴露別人不需要知道的東西笛匙。
????05-面向?qū)ο?幫助文檔的制作javadoc)
? ? ? ? 接下來秋柄,將ArrayTool.class文件發(fā)給其他人省店,其他人只要將該文件設(shè)置到classpath路徑下,就可以使用該工具類粗俱。
? ? ? ? 但是,很遺憾偏塞,該類中到底定義了多少個方法,使用者并不清楚。因為該類中并沒有說明書沧卢。
????????工具類做好了,使用者不會使用怎么辦呢立磁?這個時候就需要制作說明書。
? ? ? ? 開始制作程序的說明書几于。java的說明書通過文檔注釋來完成。
? ? ? ? 現(xiàn)在文檔注釋已經(jīng)寫完了漆弄,我們需要用另外的工具對文檔注釋進行提取和輸出推沸。
? ? ? ? 這個工具叫javadoc。
? ? ? ? 如果想把一個類生成幫助文檔宇驾,這個類必須是公共類,要加上public修飾符筝尾。
? ? ? ? 這樣就成功啦:
? ? ? ? 生成了好多文件,我們看哪一個呢损姜?一個一個去看嗎?哈哈哈。當(dāng)然是看這個啦:
? ? ? ? 打開后是醬紫:
? ? ? ? 注意私有的方法是不會出現(xiàn)在這個文檔中的哦岩齿。只有兩種權(quán)限的方法才會被提取到這個文檔中龄章,一個叫public岗憋,一個叫protect。
? ? ? ? 點擊方法進去是這樣的监徘,注意不會顯示具體的實現(xiàn)細節(jié)哦,直接拿去用就可以了户敬,使用者不用了解它怎么實現(xiàn)的。
? ? ? ? 注意這里面試沒有構(gòu)造函數(shù)的哦,因為構(gòu)造函數(shù)是私有的:
? ? ? ? 我們修改一下,不私有但是也不加公有往衷,發(fā)現(xiàn)說明文檔里依然不會顯示。
? ? ? ? 加上public修飾符:
? ? ? ? 有啦:
? ? ? ? 一個類中默認(rèn)會有一個空參數(shù)的構(gòu)造函數(shù)。
? ? ? ? 這個默認(rèn)的構(gòu)造函數(shù)的權(quán)限和所屬類一致项阴。
? ? ? ? 如果類被public修飾环揽,那么默認(rèn)的構(gòu)造函數(shù)也帶public修飾符。
? ? ? ? 如果類沒有被public修飾通今,那么默認(rèn)的構(gòu)造函數(shù),也沒有public修飾璃氢。
? ? ? ? 默認(rèn)構(gòu)造函數(shù)的權(quán)限是隨著類的變化而變化的。
? ? ? ? 當(dāng)然椰苟,不要以為如下的構(gòu)造函數(shù)就是默認(rèn)構(gòu)造函數(shù):
? ? ? ? 這是一個空參數(shù)構(gòu)造函數(shù)洁仗,而不是默認(rèn)構(gòu)造函數(shù)赠潦,這樣寫叫自定義構(gòu)造函數(shù)。不寫的話绷跑,構(gòu)造函數(shù)就是默認(rèn)的。默認(rèn)是看不見的:
? ? ? ? 剛剛做的那個文檔带膜,叫程序的說明文檔或者幫助文檔式廷,也叫做API文檔蝗肪。
? ? ? ? API是什么呢?
? ? ? ? API的全稱是:Appliacation Program Interface(應(yīng)用程序接口)。
? ? ? ? Java為了讓用戶方便使用诱咏,也做了一個幫助文檔。
? ? ? ? 所不同的是,我們剛剛做的只有一個類早处,而這個幫助文檔有好多類。而且這些類還被分別存儲到不同的包中乙濒。
? ? ? ? 比如說java.lang這個包:
? ? ? ? 比如Array這個類中的方法:
? ? ? ? 有了幫助文檔真方便陕赃!
? ? ? ? 我們寫好了幫助文檔卵蛉,需要把類(.class文件)和幫助文檔一并發(fā)過去,讓用戶使用~
????06-面向?qū)ο?靜態(tài)代碼塊)
? ? ? ? 接下來說一個小知識點么库,靜態(tài)代碼塊葡缰。
? ? ? ? 靜態(tài)代碼塊格式: ? ? ? ?
? ? ? ? static
? ? ? ? {
? ? ? ? ? ? ? ? 靜態(tài)代碼塊中的執(zhí)行語句。
? ? ? ? }
? ? ? ? 比如:
? ? ? ? 可是它也沒有名字裙顽,沒人調(diào)用怎么執(zhí)行呢梆掸?
? ? ? ? 注意徒恋,靜態(tài)代碼塊的特點:
? ? ? ? 隨著類的加載而執(zhí)行,只執(zhí)行一次带斑,并優(yōu)先于主函數(shù)。
? ? ? ? 用于給類進行初始化。
? ? ? ? 當(dāng)然這個相對少用一點,一般都是給對象初始化比較多焙格。
? ? ? ? 這樣一段程序:
? ? ? ? 它的執(zhí)行結(jié)果是怎樣呢肝陪?
? ? ? ? 我們來分析一下:
? ? ? ? 因此運行結(jié)果的打印順序為:
? ? ? ? b c a over
? ? ? ? 是不是類必須要有對象才能加載靜態(tài)代碼塊呢霹娄?
? ? ? ? 不是的计济。
? ? ? ? 定義一個靜態(tài)方法show()彤守,采用類名調(diào)用,想要調(diào)用這個方法宾濒,就必須加載StaticCode類,因此靜態(tài)代碼塊就會被加載垫蛆。
? ? ? ? 但這種情況下靜態(tài)代碼塊不會被加載,因為類沒有存在的意義:
? ? ? ? 加上以下任意一句凯亮,靜態(tài)代碼塊就被加載了创千,因為用到了類中的函數(shù)。
? ? ? ? 可能會有疑惑拆挥,第一句用到了類中的什么呢男翰?用到了類里面的默認(rèn)構(gòu)造函數(shù)呀。
? ? ? ? 增加一丟丟難度晤揣,StaticCode類中這樣寫: ? ? ? ?
? ? ? ? StaticDemo類中這樣寫:
????????運行結(jié)果會怎樣呢?????????
? ? ? ? 運行結(jié)果是:a c d
? ? ? ? 分析一下:
????????再一個問題:
? ? ? ? 報錯啦烤宙。
? ? ? ? 因為靜態(tài)代碼塊,只能訪問靜態(tài)變量梧奢。
? ? ? ? 但在構(gòu)造代碼塊中就闊以:
? ??07-面向?qū)ο?對象的初始化過程)
????????Person p=new Person("zhangsan",20); ? ? ? ?
? ? ? ? 這句話都做了什么事情?
? ? ? ? 1抡蛙,因為new用到了Person.class,所以會先找到Person.class文件并加載到內(nèi)存中蜂奸。
? ? ? ? 2儒鹿,執(zhí)行該類中的static代碼塊剖淀,如果有的話,給Person.class類進行初始化绅作。
? ? ? ? 3萎津,在堆內(nèi)存中開辟空間唬党,分配內(nèi)存地址。
? ? ? ? 4鬼佣,在對內(nèi)存中建立對象的特有屬性驶拱,并進行默認(rèn)初始化。
? ? ? ? 5晶衷,對屬性進行顯式初始化蓝纲。
? ? ? ? 6,對對象進行構(gòu)造代碼塊初始化晌纫。
? ? ? ? 7税迷,對對象進行對應(yīng)的構(gòu)造函數(shù)初始化。
? ? ? ? 8锹漱,將內(nèi)存地址賦給棧內(nèi)存中的p變量箭养。
????08-面向?qū)ο?對象調(diào)用成員過程)
? ? ? ? 圖有點小亂,棧內(nèi)存中大概就是如下的過程:
? ? ? ? 這樣才對哦:
? ??09-面向?qū)ο?單例設(shè)計模式)
? ? ? ? 設(shè)計模式:解決某一類問題最行之有效的方法哥牍。
? ? ? ? java中23中涉及模式:
? ? ? ? 單例設(shè)計模式:解決一個類在內(nèi)存只存在一個對象毕泌。
? ? ? ? 想要保證對象唯一的原因:
? ? ? ? 1喝检,為了避免其他程序過多建立該類對象。先禁止其他程序建立該類對象撼泛。
? ? ? ? 2蛇耀,還為了讓其他程序可以訪問到該類對象,只好在本類中坎弯,自定義一個對象。
? ? ? ? 3译暂,為了方便其他程序?qū)ψ远x對象的訪問抠忘,可以對外提供一些訪問方式。
? ? ? ? 這三步具體怎么用代碼體現(xiàn)呢外永?
? ? ? ? 1崎脉,將構(gòu)造函數(shù)私有化。
? ? ? ? 2伯顶,在類中創(chuàng)建一個本類對象囚灼。
? ? ? ? 3,提供一個方法可以獲取到該對象祭衩。
? ? ? ? 整體是這樣的:
? ? ? ? 但是有個問題灶体,沒有對象就沒有辦法調(diào)用這個方法,所以需要將這個方法用static修飾掐暮。而靜態(tài)方法只能訪問靜態(tài)成員蝎抽,因此s也需要被static修飾,同時s只是在類內(nèi)部被調(diào)用路克,所以將它私有化樟结。
? ? ? ? 內(nèi)存中是這樣的:
? ? ? ? 不管new多少個對象,都指向同一個對象精算,內(nèi)存中只存在一個瓢宦,保證了對象的唯一性。
? ? ? ? 運行下面這段程序:
? ? ? ? 運行結(jié)果:
? ? ? ? 將Single(){}私有化:
? ? ? ? 運行結(jié)果:
? ? ? ? 對于事物該怎么描述灰羽,還怎么描述驮履。
? ? ? ? 當(dāng)需要將該事物的對象保證在內(nèi)存中唯一時,就將以上的三步加上即可谦趣。
????10-面向?qū)ο?單例設(shè)計模式方式二)
? ? ? ? 兩種初始化方式:
? ? ? ? 餓漢式:
? ? ? ? 先初始化對象疲吸。
? ? ? ? Single類一進內(nèi)存,就已經(jīng)創(chuàng)建好了對象前鹅。
? ? ? ? 懶漢式:
? ? ? ? 對象是方法被調(diào)用時摘悴,才初始化。也叫做對象的延時加載舰绘。
? ? ? ? Single類進內(nèi)存蹂喻,對象還沒有存在葱椭,只有調(diào)用了getInstance方法時,才建立對象口四。
? ? ? ? 其實先創(chuàng)建后創(chuàng)建也都差不多孵运,區(qū)別不大。懶漢式一般實際開發(fā)中不常用蔓彩,什么時候用呢治笨?面試的時候用,哈哈赤嚼。注意開發(fā)一般用餓漢式旷赖,因為它安全,而且簡單更卒。
? ? ? ? 而懶漢式存在一個問題等孵,如果一個人調(diào)用這個方法,沒有問題蹂空。如果多個人同時調(diào)用這個方法俯萌,就會發(fā)生問題。
? ? ? ? A上枕、B先后進來咐熙,A new了一個對象,return了辨萍,B也跟著new了一個對象糖声,這個時候?qū)ο缶筒晃ㄒ涣恕?/p>
? ? ? ? 也有解決方法,加一個鎖分瘦,這樣A進去之后蘸泻,其他就進不去了。
? ? ? ? 但是用了這個鎖嘲玫,運行效率就降低了悦施,每次要用這個功能,都得先判斷一下里面有人沒去团。
? ? ? ? 有沒有既不低效又有用的方法呢抡诞?
????????我們可以用雙重判斷的方法來完成,最終解決方案:
? ? ? ? 它相對不低效的原因是減少了用鎖的次數(shù)土陪,剛開始第一個第二個會判斷時候可以開鎖昼汗,后面的在第一個if(s==null)這里就被攔住了,直接return s鬼雀。
? ? ? ? 這個方法雖然不低效了顷窒,但是代碼量大了。
? ? ? ? 所以還是餓漢式方法更好用一些。而且餓漢式不會出問題的鞋吉,因為它里面就一句話鸦做,return s。
? ? ? ? 記住原則:定義單例谓着,建議用餓漢式泼诱。
? ? ? ? 2018-12-3
? ? ? ? 之前結(jié)尾還有一丟丟沒有寫詳細,今天整理完day07的筆記后又將這邊結(jié)尾處重新補充完整了赊锚,這下沒遺憾了治筒,嘻嘻。
? ? ? ? 補這個后記湊一下字?jǐn)?shù)舷蒲,本篇也5000+啦矢炼。