Java是一門純粹的OOP(Object-Oriented Programming)[面向?qū)ο骫的編程語(yǔ)言弄唧。所以其實(shí)從這里開始才是重點(diǎn)哈哈广匙。
面向?qū)ο笞钤缡瞧呤甏臅r(shí)候由IBM的SmallTalk語(yǔ)言最先推廣,后來有了C++,再后來產(chǎn)生了今天的Java。
面向?qū)ο?/h1>
面向?qū)ο笫且环N技術(shù)的開發(fā)模式家卖,但是最早的時(shí)候所使用的模式是面向過程。
“面向過程”(Procedure Oriented) 是一種以過程為中心的編程思想庙楚。這些都是以什么正在發(fā)生為主要目標(biāo)進(jìn)行編程篡九,不同于面向?qū)ο蟮氖钦l(shuí)在受影響。與面向?qū)ο竺黠@的不同就是封裝醋奠、繼承、類伊佃。
面向過程:是針對(duì)某一個(gè)問題單獨(dú)提出解決方案以及代碼開發(fā)窜司。只能解決當(dāng)前問題,由于缺少合理做法航揉,只能完成一次服務(wù)塞祈,為特定功能服務(wù)。
面向?qū)ο螅菏前褬?gòu)成問題事務(wù)分解成各個(gè)對(duì)象帅涂,建立對(duì)象的目的不是為了完成一個(gè)步驟议薪,而是為了描敘某個(gè)事物在整個(gè)解決問題的步驟中的行為。
面向?qū)ο笫且砸环N組件化的形式進(jìn)行代碼的設(shè)計(jì)媳友。這樣開發(fā)出來的代碼有一個(gè)最大的好處就是重用斯议。
舉個(gè)栗子:
小王開了一家正裝店鋪,關(guān)于西服的進(jìn)貨醇锚,他現(xiàn)在有兩種選擇:
- 來一個(gè)客人之后哼御,量好身材,制作上衣焊唬、褲子恋昼、領(lǐng)帶。然后交付給客人赶促。(面向過程)
- 按照每一個(gè)尺碼分別制作若干上衣液肌、褲子、領(lǐng)帶鸥滨,客人直接按尺碼購(gòu)買嗦哆。(面向?qū)ο螅?/li>
在面向?qū)ο蟮某绦蛑杏腥N特性:
- 封裝性:保護(hù)內(nèi)部的定義結(jié)構(gòu)安全性
- 繼承性:在已有程序結(jié)構(gòu)上繼續(xù)擴(kuò)充新的功能
- 多態(tài)性:在某一個(gè)概念范圍內(nèi)的滿足
面向?qū)ο箝_發(fā)的步驟分為:OOA(面向?qū)ο蠓治觯OD(面向?qū)ο笤O(shè)計(jì))爵赵、OOP(面向?qū)ο缶幊蹋?/p>
類與對(duì)象
面向?qū)ο笥袃蓚€(gè)基本概念:類與對(duì)象吝秕。
- 類:是對(duì)客觀事物不斷認(rèn)識(shí)而產(chǎn)生的一個(gè)抽象概念
- 對(duì)象:現(xiàn)實(shí)生活中的一個(gè)個(gè)實(shí)體(也稱實(shí)例)
類就是共性的集合,對(duì)象就是某一個(gè)性的產(chǎn)物空幻。
類是現(xiàn)實(shí)世界或思維世界中的實(shí)體在計(jì)算機(jī)中的反映烁峭,它將數(shù)據(jù)以及這些數(shù)據(jù)上的操作封裝在一起。 from 百度百科
相似的對(duì)象可以歸并為一類(共性集合),就與1约郁、2缩挑、3都是整數(shù),可以歸類到int類型里一樣鬓梅,所以同一個(gè)類所創(chuàng)建出的對(duì)象供置,它的值可以不相同,但是屬性一定相同绽快。比如1和2芥丧,他們一個(gè)數(shù)值上不相等,但是屬性上都是整數(shù)坊罢。
找個(gè)人干活 找到了小王同學(xué) 人就是類续担,小王同學(xué)就是對(duì)象~
去銀行辦一個(gè)賬戶,賬戶是類活孩,辦到的銀行卡是對(duì)象物遇。
招聘時(shí)HR需要的是附和他要求的那一類人,如果你每一項(xiàng)剛好符合他的需求憾儒,你就是他要找的對(duì)象询兴。
基本定義
如果需要定義一個(gè)類的話,可以使用class 類名稱{ }
起趾。類中的組成主要有兩點(diǎn):
- Field(屬性诗舰,成員,變量)就是一堆變量的集合
- Method(方法训裆,行為)之前學(xué)過的方法始衅,但是此時(shí)的方法是由對(duì)象調(diào)用的。
定義一個(gè)類:
class book{ //定義一個(gè)新的類
String title; //書的名字
double price; //書的價(jià)格
public void getInfo(){//此方法將由對(duì)象調(diào)用
System.out.println("圖書名稱:"+title+"缭保,價(jià)格:"+price);
}
}
那么這個(gè)類里定義了兩個(gè)屬性和一個(gè)方法汛闸。有類之后,如果想要使用類的話艺骂,就必須有對(duì)象诸老,對(duì)象的定義分為兩種格式:
- 聲明對(duì)象并實(shí)例化:類名稱 對(duì)象名稱 = new 類名稱();
- 分步完成:① 聲明對(duì)象:類名稱 對(duì)象名稱 = null; ② 實(shí)例化對(duì)象:對(duì)象名稱 = new 類名稱();
類屬于引用數(shù)據(jù)類型,而引用數(shù)據(jù)類型與基本數(shù)據(jù)類型最大的不同在于引用數(shù)據(jù)類型需要開辟內(nèi)存空間钳恕,我們使用new
關(guān)鍵字來進(jìn)行內(nèi)存空間的開辟别伏。但是說到內(nèi)存之前,需要普及兩個(gè)概念:
堆棧(stack)忧额。位于通用 RAM 中厘肮,但通過它的 “堆棧指針” 可以從處理器哪里獲得支持。堆棧指針若向下移動(dòng)睦番,則分配新的內(nèi)存类茂;若向上移動(dòng)耍属,則釋放那些 內(nèi)存。這是一種快速有效的分配存儲(chǔ)方法巩检,僅次于寄存器厚骗。創(chuàng)建程序時(shí)候,JAVA 編譯器必須知道存儲(chǔ)在堆棧內(nèi)所有數(shù)據(jù)的確切大小和生命周期兢哭,因?yàn)樗仨毶?相應(yīng)的代碼领舰,以便上下移動(dòng)堆棧指針。這一約束限制了程序的靈活性迟螺,所以雖然某些 JAVA 數(shù)據(jù)存儲(chǔ)在堆棧中——特別是對(duì)象引用冲秽,但是 JAVA 對(duì)象不存儲(chǔ)其 中。
堆(heap)矩父。一種通用性的內(nèi)存池(也存在于 RAM 中)劳跃,用于存放所以的 JAVA 對(duì)象。堆不同于堆棧的好處是:編譯器不需要知道要從堆里分配多少存儲(chǔ)區(qū) 域浙垫,也不必知道存儲(chǔ)的數(shù)據(jù)在堆里存活多長(zhǎng)時(shí)間。因此郑诺,在堆里分配存儲(chǔ)有很大的靈活性夹姥。當(dāng)你需要?jiǎng)?chuàng)建一個(gè)對(duì)象的時(shí)候,只需要 new 寫一行簡(jiǎn)單的代碼辙诞,當(dāng)執(zhí)行 這行代碼時(shí)辙售,會(huì)自動(dòng)在堆里進(jìn)行存儲(chǔ)分配。當(dāng)然飞涂,為這種靈活性必須要付出相應(yīng)的代碼旦部。用>堆進(jìn)行存儲(chǔ)分配比用堆棧進(jìn)行存儲(chǔ)存儲(chǔ)需要更多的時(shí)間。
這一段太長(zhǎng)了哈较店,其實(shí)簡(jiǎn)單的來說士八,堆內(nèi)存保存的是每一個(gè)對(duì)象的屬性內(nèi)容,new
關(guān)鍵字開辟的內(nèi)存空間也正是它梁呈。而棧內(nèi)存存放的是一塊堆內(nèi)存的地址婚度,能夠告訴機(jī)器這個(gè)東西存在哪里。
比如超市的儲(chǔ)物柜官卡,你按一下按鈕蝗茁,會(huì)打開一個(gè)柜子,并且出來一張條形碼的紙條寻咒。結(jié)賬完之后拿包什么的只需要拿著那個(gè)條形碼去掃一下就可以打開那個(gè)柜子哮翘。那么,打開的柜子就是你按下按鈕(new)開辟的“堆內(nèi)存”空間毛秘,出來的條形碼就是“棧內(nèi)存”饭寺,里面存放的是這個(gè)柜子的地址信息,可能是第幾排第幾個(gè),也可能是編號(hào)001號(hào)柜子佩研。
好柑肴,概念了解完就可以繼續(xù)了~
當(dāng)一個(gè)對(duì)象實(shí)例化之后就可以按照下列方式利用對(duì)象操作類:
- 對(duì)象.屬性 表示要操作類中的屬性內(nèi)容
- 對(duì)象.方法() 表示要調(diào)用類中的方法
那么就使用一下剛剛的book類吧:
public class Test01{
public static void main(String[] args){
Book bk=new Book();//聲明并實(shí)例化對(duì)象
bk.title="Java開發(fā)";//操作屬性內(nèi)容
bk.price=89.9;//操作屬性內(nèi)容
bk.getInfo();//調(diào)用類中的getInfo方法
}
}
分析一下:
Book bk=new Book();//聲明并實(shí)例化對(duì)象
聲明了bk對(duì)象,并且為bk對(duì)象new了一個(gè)堆內(nèi)存空間旬薯。(堆內(nèi)存:title=null price=0.0)ps. String是引用數(shù)據(jù)類型晰骑,所以默認(rèn)值為null,double型的price默認(rèn)值為0.0
bk.title="Java開發(fā)";//操作屬性內(nèi)容
修改bk對(duì)象的title(堆內(nèi)存:title="Java開發(fā)" price=0.0)
bk.price=89.9;//操作屬性內(nèi)容
修改bk對(duì)象的price(堆內(nèi)存:title="Java開發(fā)" price=89.9)
那么如果是分步來呢绊序?
Book bk;//聲明對(duì)象
bk = new Book();//實(shí)例化對(duì)象
依然還是來分析一下哈:
Book bk;//聲明對(duì)象
聲明了bk對(duì)象硕舆,由于沒有實(shí)例化,所以目前的bk對(duì)象為引用類型的默認(rèn)值null
骤公。
bk = new Book();//實(shí)例化對(duì)象
實(shí)例化bk對(duì)象抚官,new開辟了bk的內(nèi)存空間,所以bk就不為空了(但是里面的屬性是默認(rèn)值null和0.0)
任何情況下只要出現(xiàn)了關(guān)鍵字new
阶捆,都表示要開辟新的內(nèi)存空間凌节,一旦堆內(nèi)存空間開辟了,里面就一定會(huì)有所有類中定義的屬性洒试,當(dāng)然所有的屬性的值都是它對(duì)應(yīng)的數(shù)據(jù)類型的默認(rèn)值
我們?cè)诼暶鲗?duì)象之后一定要記得實(shí)例化對(duì)象倍奢,如果忘記的話:
public class Test01 {
public static void main(String[] args) {
Book bk;
// bk = new Book(); //模擬沒有初始化
bk.title = "測(cè)試用書";
bk.price = 100.1;
bk.getInfo();
}
}
輸出的結(jié)果:
Exception in thread "main" java.lang.NullPointerException
at Test01.main(Test01.java:11)
NullPointerException 空指針異常
開辟了堆內(nèi)存的對(duì)象叫實(shí)例化對(duì)象,但是如果使用未實(shí)例化的對(duì)象垒棋,程序在運(yùn)行時(shí)就會(huì)出現(xiàn)空指針異常卒煞。
(編譯的過程中報(bào)的錯(cuò)誤屬于語(yǔ)法錯(cuò)誤,空指針這個(gè)是運(yùn)行時(shí)報(bào)錯(cuò))
引用數(shù)據(jù)
引用 是Java的核心精髓所在叼架。引用類似于C++中的指針概念畔裕,但是比指針更加的簡(jiǎn)單。
在所有的引用分析里乖订,最關(guān)鍵的還是在于關(guān)鍵字"new"扮饶,一定要注意每一次使用關(guān)鍵詞new都一定會(huì)開辟新的堆內(nèi)存空間,所以代碼里聲明了兩個(gè)對(duì)象乍构,并且分別進(jìn)行了實(shí)例化操作贴届,那么一定是開辟了兩個(gè)堆內(nèi)存空間,互不影響蜡吧。
舉個(gè)栗子 01:
Book bk1 = new Book();
Book bk2 = null;
聲明了兩個(gè)對(duì)象了毫蚓,但是只實(shí)例化了bk1,也就是說只開辟了bk1這一個(gè)內(nèi)存空間昔善。
bk1.title = "Java開發(fā)"; // 操作屬性內(nèi)容
bk1.price = 89.9; // 操作屬性內(nèi)容
修改了bk1的屬性值
bk2 = bk1; // 引用傳遞
這句話元潘,將bk1賦值給bk2。意思就是將bk1的堆內(nèi)存空間的地址給了bk2的棧內(nèi)存君仆,所以bk2與bk1目前指向的是同一塊堆內(nèi)存翩概。
bk2.title = "JSP開發(fā)"; // 操作屬性內(nèi)容
bk2.price = 68.8; // 操作屬性內(nèi)容
修改了bk2指向的堆內(nèi)存中的數(shù)據(jù)牲距。但是由于bk2和bk1指向的是同一個(gè)堆內(nèi)存,所以bk1也同樣修改了
bk1.getInfo(); // 調(diào)用類中的getInfo方法
bk2.getInfo(); // 調(diào)用類中的getInfo方法
所以這里bk1和bk2的getInfo()方法輸出的結(jié)果是一樣的钥庇!
舉個(gè)栗子 02:
Book bk1 = new Book();
Book bk2 = new Book();
bk1.title = "Java開發(fā)"; // 操作屬性內(nèi)容
bk1.price = 89.9; // 操作屬性內(nèi)容
bk2 = bk1; // 引用傳遞
bk2.title = "JSP開發(fā)"; // 操作屬性內(nèi)容
bk2.price = 68.8; // 操作屬性內(nèi)容
bk1.getInfo(); // 調(diào)用類中的getInfo方法
bk2.getInfo(); // 調(diào)用類中的getInfo方法
這一次的bk2也被實(shí)例化了牍鞠,也就是說開辟了兩個(gè)堆內(nèi)存空間。但是在第五行的時(shí)候评姨,bk2再一次的指向了bk1的堆內(nèi)存地址难述!于是,bk2原來的堆內(nèi)存空間就沒有任何棧內(nèi)存指向它了吐句,所以這個(gè)沒有任何棧內(nèi)存指向的堆內(nèi)存胁后,就將成為垃圾。
所有的垃圾會(huì)不定期的被垃圾收集器(GC)進(jìn)行回收嗦枢,回收之后會(huì)釋放掉其所占用的空間攀芯。
ps. 雖然Java中有支持自動(dòng)的垃圾收集處理,但在開發(fā)過程中應(yīng)該盡量減少垃圾空間的產(chǎn)生文虏。
以上侣诺,修改于 20190512 。
學(xué)自李興華老師的Java課
from ahanwhite
如有錯(cuò)誤氧秘,敬請(qǐng)批評(píng)年鸳!非常感謝。