java基礎(chǔ)知識(shí)—面向?qū)ο蠛屠^承
一堂污、變量
- 靜態(tài)變量
- 成員變量
- 局部變量
詳情可見(jiàn) 淺談Java變量。
二官紫、修飾符
詳情可見(jiàn) 梳理Java修飾符引瀑。
三狂芋、Java方法參數(shù)——按值傳遞
首先回顧兩個(gè)概念:
1.按值傳遞:表示方法接受的是調(diào)用者提供的值
2.按引用傳遞:表示方法接受的是調(diào)用者提供的變量的地址
其中:方法是可以修改按引用傳遞的變量的值
Java語(yǔ)言總是采用按照按值傳遞,也就是說(shuō)java 的方法不能改變傳遞給它的任何參數(shù)變量的內(nèi)容
舉個(gè)栗子:
double percent = 10;
tripleValue(percent);
public static void tripleValue(double x) {
x = 3 * x;
}
運(yùn)行如上代碼你會(huì)發(fā)現(xiàn):percent的值依舊是10憨栽。下面我們?cè)敿?xì)分解一下具體執(zhí)行的過(guò)程:
1.x初始化為percent值得一個(gè)副本(也就是10)帜矾;
2.x乘以3后等于30翼虫,但是percent仍然是10.(如下圖所示)
3.方法結(jié)束后,參數(shù)變量x不再使用屡萤。
上面的例子我們可以看到是使用了基本類型珍剑,然而方法的參數(shù)除了基本類型之外,還有對(duì)象引用灭衷,我們已經(jīng)通過(guò)上面的例子已經(jīng)知道了次慢,方法是不可能改變基本類型的,而對(duì)象引用作為參數(shù)就不同了翔曲。我們看下面這個(gè)例子:
harry = new Employee(...);
tripleValue(harry);
public static void tripleValue(Employee x) {
x.raiseSalary(200);
}
運(yùn)行上面的代碼,我們可以看到harry的工資確實(shí)增長(zhǎng)了200劈愚;這是為什么呢瞳遍?我們來(lái)看一下具體的執(zhí)行過(guò)程:
1.x初始化為harry值得一個(gè)副本,注意:這里是一個(gè)對(duì)象的引用
2.raiseSalary方法應(yīng)用于這個(gè)對(duì)象引用菌羽。x和harry同時(shí)引用的都是同一個(gè)Employee的對(duì)象掠械。(如下圖所示)
3.方法結(jié)束后,x不再使用注祖。但是harry依舊引用了那個(gè)Employee的對(duì)象
由此可以看到猾蒂,實(shí)現(xiàn)一個(gè)改變對(duì)象參數(shù)狀態(tài)的方法是完全可以的,所以有人會(huì)有疑問(wèn)是晨,這樣不就跟上面所述的java 的方法不能改變傳遞給它的任何參數(shù)變量的內(nèi)容
自相矛盾了嗎肚菠?其實(shí)不然,我們可以看到第二個(gè)例子中罩缴,方法中傳遞的是對(duì)象的引用蚊逢,也就是指向這個(gè)對(duì)象的地址,依舊是一個(gè)值箫章。所以由此可以說(shuō)明java方法中,是采用按值傳遞的原則,對(duì)象的引用實(shí)際上也是按值傳遞
四魂奥、Java中的三大特點(diǎn):封裝势木、繼承和多態(tài)
1.什么是封裝
封裝:從形式上看,封裝就是將數(shù)據(jù)和行為組合在一個(gè)包中桶至,并對(duì)對(duì)象的使用者隱藏具體的實(shí)現(xiàn)方法昼伴。簡(jiǎn)言之,把對(duì)象的屬性私有化塞茅,通過(guò)提供對(duì)外可用的方法來(lái)訪問(wèn)屬性亩码。封裝給對(duì)象賦予了“黑盒”的特性。
2.什么是繼承
繼承:繼承的基本思想就是可以基于已有的類創(chuàng)建新的類野瘦。繼承已經(jīng)存在的類就是繼承這些類的方法描沟。我們可以用“is - a”的關(guān)系來(lái)描述繼承飒泻。
關(guān)于繼承,可以詳情可見(jiàn) 吏廉。
3.什么是多態(tài)
多態(tài):一個(gè)對(duì)象變量可指示多個(gè)實(shí)際類型的現(xiàn)象稱為多態(tài)泞遗。在程序運(yùn)行時(shí),才能夠自動(dòng)地選擇適當(dāng)?shù)姆椒ㄏ病S纱丝梢悦靼资氛蓿琷ava程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定佩伤。這種在運(yùn)行時(shí)才決定使用哪兒中方法的現(xiàn)象稱之為“動(dòng)態(tài)綁定”聊倔。
4.方法調(diào)用
由于多態(tài)性的存在,準(zhǔn)確理解如何在對(duì)象上應(yīng)用方法調(diào)用肥腸重要:)生巡,下面根據(jù)一個(gè)例子詳細(xì)介紹調(diào)用過(guò)程的步驟:
例:假設(shè)需要調(diào)用 x.f(String)
,隱式參數(shù)x聲明為類C的一個(gè)對(duì)象耙蔑。
1.編譯器查看對(duì)象的聲明類型和方法名。需要注意孤荣,有可能存在多個(gè)名字為f但參數(shù)類型不一樣的方法甸陌。例如:f(int)
,f(String)
,編譯器會(huì)一一列舉C類中所有名為f的方法和超類中所有名為f且可以訪問(wèn)的方法。盐股。至此钱豁,編譯器已經(jīng)知道所有可能被調(diào)用的候選方法。
2.編譯器需要確定方法調(diào)用中提供的參數(shù)類型疯汁。如果所有候選列表中存在一個(gè)與所提供的參數(shù)類型完全匹配的方法牲尺,則選擇此方法。這個(gè)過(guò)程叫做重載解析涛目。至此編譯器已經(jīng)知道需要調(diào)用的方法名和參數(shù)類型秸谢。
3.如果是private
方法,static
方法,final
方法或者構(gòu)造器霹肝,那么編譯器可以準(zhǔn)確的知道應(yīng)調(diào)用哪兒個(gè)方法估蹄。這個(gè)稱為“靜態(tài)綁定”。與之對(duì)應(yīng)沫换,如果要調(diào)用的方法依賴于隱式參數(shù)的實(shí)際類型臭蚁,那么必選在運(yùn)行時(shí)使用動(dòng)態(tài)綁定。在該例子中會(huì)利用動(dòng)態(tài)綁定生成一個(gè)調(diào)用f(String)的指令讯赏。
4.程序運(yùn)行且采用動(dòng)態(tài)綁定機(jī)制垮兑,虛擬機(jī)必須調(diào)用與x所引用對(duì)象的實(shí)際類型對(duì)應(yīng)的那個(gè)方法。假設(shè)x實(shí)際類型是D漱挎,D是C的子類系枪。如果D中聲明了f(String)
則調(diào)用,反之去超類中找磕谅。
五私爷、重載(overloading)與覆蓋(override)的區(qū)別
1.什么是重載(overloading)
在一個(gè)類中雾棺,如果多個(gè)方法有相同的簽名(簽名:方法名和參數(shù)類型,不包含返回類型)衬浑,便出現(xiàn)了重載捌浩。無(wú)參構(gòu)造函數(shù)和有參構(gòu)造函數(shù)是最明顯的例子了。
2.什么是覆蓋(override)
覆蓋(override)適用于繼承當(dāng)中的工秩,當(dāng)子類中的某個(gè)方法的簽名和超類的方法簽名一樣尸饺,則出現(xiàn)了覆蓋。出現(xiàn)覆蓋的原因在于助币,有的時(shí)候父類中的部分方法不適用與子類浪听。
例如:父類為Employee,子類為Manager奠支,父類中有個(gè)getSalary的方法馋辈,但是由于子類Manager中的getSalary的方法想返回基本工資和獎(jiǎng)金(普通員工沒(méi)有),則需要在子類中重新實(shí)現(xiàn)getSalary的方法倍谜,即覆蓋,格式如下(使用super
的關(guān)鍵字):
public double getSalary() {
double baseSalary = super.getSalary(); // 此處調(diào)用了父類的getSalary的方法
return baseSalary + bonus;
}
**注意:在覆蓋中叉抡,返回值的范圍要小于父類尔崔,拋出的異常范圍小于等于父類,訪問(wèn)修飾符不能低于父類褥民,如果父類中的方法修飾符為private季春,則子類就不能重寫此方法。
六消返、自動(dòng)裝箱和拆箱
- 裝箱:將基本類型用它們對(duì)應(yīng)的引用類型包裝起來(lái)载弄;
- 拆箱:將包裝類型轉(zhuǎn)換為基本數(shù)據(jù)類型;
七撵颊、equals和hashCode
在我們coding過(guò)程中宇攻,經(jīng)常碰到重寫equals方法,但是我們?yōu)槭裁粗貙慹quals的時(shí)候必須重寫hashCode()方法呢倡勇?
1)逞刷、如果兩個(gè)對(duì)象相等,那么它們的hashCode()值一定相同妻熊。這里的相等是指夸浅,通過(guò)equals()比較兩個(gè)對(duì)象時(shí)返回true。
2)扔役、如果兩個(gè)對(duì)象hashCode()相等帆喇,它們并不一定相等。因?yàn)樵谏⒘斜碇幸谛兀琱ashCode()相等坯钦,即兩個(gè)鍵值對(duì)的哈希值相等预皇。然而哈希值相等,并不一定能得出鍵值對(duì)相等葫笼。補(bǔ)充說(shuō)一句:“兩個(gè)不同的鍵值對(duì)深啤,哈希值相等”,這就是哈希沖突路星。
此外溯街,在這種情況下。若要判斷兩個(gè)對(duì)象是否相等洋丐,除了要覆蓋equals()之外呈昔,也要覆蓋hashCode()函數(shù)。否則友绝,equals()無(wú)效堤尾。
例如,創(chuàng)建Person類的HashSet集合迁客,必須同時(shí)覆蓋Person類的equals() 和 hashCode()方法郭宝。如果單單只是覆蓋equals()方法。我們會(huì)發(fā)現(xiàn)掷漱,equals()方法沒(méi)有達(dá)到我們想要的效果粘室。