搬磚也要搬的不一般。
一、前言
歲月匆匆而來(lái),時(shí)光匆匆而去。轉(zhuǎn)眼間,做java開(kāi)發(fā)已有3、4年的時(shí)間了,期間做過(guò)后臺(tái)開(kāi)發(fā),寫過(guò)前端web,而最主要的則是做android開(kāi)發(fā)。語(yǔ)言也接觸過(guò)好多種,什么Python、Kotlin、swift、Js、C等等,而最讓我迷戀的還是個(gè)java。
java的優(yōu)點(diǎn)我便不多說(shuō)了,網(wǎng)上有太多的解釋。而本文則是我三年來(lái)對(duì)java的理解,以及對(duì)網(wǎng)上收集資料的總結(jié),是最java進(jìn)階的知識(shí)整理。
進(jìn)入編程的第四年,不應(yīng)該僅僅處于java的使用,而java的理解才是一道不得不邁的一道坎。
二、java第一步:啥是面向?qū)ο?/h2>
2種主流的開(kāi)發(fā)方法:結(jié)構(gòu)化程序設(shè)計(jì)和面向?qū)ο蟪绦蛟O(shè)計(jì);
* 結(jié)構(gòu)化程序設(shè)計(jì):
理解:
2種主流的開(kāi)發(fā)方法:結(jié)構(gòu)化程序設(shè)計(jì)和面向?qū)ο蟪绦蛟O(shè)計(jì);
結(jié)構(gòu)化程序設(shè)計(jì)就是將程序功能,進(jìn)行一層一層的剝離,進(jìn)行功能細(xì)分。一個(gè)細(xì)分功能就是一個(gè)函數(shù),然后再由上層函數(shù)進(jìn)行調(diào)用,在函數(shù)的層層調(diào)用之后,最終由主函數(shù)進(jìn)行調(diào)用,實(shí)現(xiàn)完整的功能。
原則:
自頂向下、逐步求精、模塊化。
* 面向?qū)ο蟪绦蛟O(shè)計(jì):
理解:
1.什么是對(duì)象?
對(duì)象是實(shí)際存在的該類事物的個(gè)體,即對(duì)象是類的實(shí)例化,現(xiàn)實(shí)中的萬(wàn)物都可以理解為一個(gè)對(duì)象;
如:一輛汽車,將其抽象為具體的屬性,即速度、大小、顏色、座位數(shù)等屬性,以及具體的行為,即加速、剎車、載客等行為。
2.什么是對(duì)象?
類是具有共同屬性和行為的一組對(duì)象的抽象。類是對(duì)象的抽象表現(xiàn),是對(duì)象在代碼中的具體表現(xiàn)形式;它必須具有屬性和行為,才是一個(gè)完整的對(duì)象。
3.對(duì)象就是類?
對(duì)象是類的實(shí)例化,而類是對(duì)象的抽象;
類是面向?qū)ο缶幊讨械淖钚〉膯卧?,但是類并不一定是一個(gè)對(duì)象,而類只是對(duì)象的一種表現(xiàn)形式;
對(duì)象可以是一個(gè)類,也可以是一個(gè)函數(shù),或者多個(gè)類的集合,即萬(wàn)物皆可為對(duì)象;
而有些類在嚴(yán)格的意義上來(lái)講,卻并不是一個(gè)對(duì)象;
如: 一個(gè)僅僅包含常量的類,就不是一個(gè)對(duì)象。它僅僅具有屬性缺不具有行為。
4.面向?qū)ο蟮奶卣?/strong>
封裝、繼承、多態(tài)
- 封裝:
是把對(duì)象的屬性和行為結(jié)合成一個(gè)整體,對(duì)細(xì)節(jié)隱藏,對(duì)操作開(kāi)放。
如:一臺(tái)智能手機(jī),你不要關(guān)心手機(jī)內(nèi)部有什么?怎么運(yùn)行的程序?你只要點(diǎn)亮屏幕,就可以實(shí)現(xiàn)打電話、玩游戲、聊天等功能。
java的封裝由權(quán)限修飾符:private、public、protected、default實(shí)現(xiàn);
- 繼承:
是對(duì)一系列對(duì)象的公共屬性和行為進(jìn)行提取封裝,而后由其他類繼承,并實(shí)現(xiàn)自己獨(dú)有的屬性或行為。
父類獨(dú)立于子類,而子類則依賴于父類。
如:水果是一個(gè)父類,其具有酸、甜等屬性,也具有吃、腐爛等行為;而橘子也是水果的一種,它不僅具有父類的屬性,同時(shí)還具有剝皮的特殊行為。因此,橘子是水果的一個(gè)子類,它實(shí)現(xiàn)了父類的所有方法,但要獨(dú)立實(shí)現(xiàn)剝皮的行為。
簡(jiǎn)單說(shuō),沒(méi)有橘子,水果依舊還是水果。但是,橘子如果不能吃,那他就一定不是水果。
java的繼承使用extends或implements進(jìn)行標(biāo)記,通過(guò)override(重寫)標(biāo)記父類的行為,通過(guò)super實(shí)現(xiàn)父類的方法。
- 多態(tài):
是對(duì)象的同種行為的不同表現(xiàn)形式。
多態(tài)僅僅針對(duì)行為,與屬性無(wú)關(guān)。
java的多態(tài)可以劃分為同一個(gè)類中的多態(tài)(重載),以及父類與子類間的多態(tài)(重寫)
如:‘吃’這個(gè)行為。可以表現(xiàn)為,吃飯、吃水果、吃茶等等。
java的多態(tài),由重寫(override)和重載(overload)來(lái)實(shí)現(xiàn);
三、對(duì)象的番外篇
1.權(quán)限修飾符
| 修飾符 | 類內(nèi)部 | 本包 | 子類 | 外部包 |
|---|---|---|---|---|
| public | 可訪問(wèn) | 可訪問(wèn) | 可訪問(wèn) | 可訪問(wèn) |
| protected | 可訪問(wèn) | 可訪問(wèn) | 可訪問(wèn) | |
| default | 可訪問(wèn) | 可訪問(wèn) | ||
| private | 可訪問(wèn) |
備注:??沒(méi)有填寫的內(nèi)容為不可訪問(wèn)。
問(wèn)題:被protected標(biāo)注的外部包的子類是否可以訪問(wèn)?
答:可以訪問(wèn)的,類優(yōu)先與包,而被protected標(biāo)注的變量,在子類中是可以訪問(wèn)的。
2.重寫和重載的對(duì)比
- 什么是重寫?
重寫父類與子類之間的多態(tài)性,是子類對(duì)父類的方法重新定義,可以實(shí)現(xiàn)父類的方法,也可以不實(shí)現(xiàn)父類的方法。
即,方法名、參數(shù)與返回值完全相同,且子類方法的訪問(wèn)權(quán)限不可以小于類;
- 什么是重載?
重載是在同一個(gè)類中,相同的行為的不同表現(xiàn)形式。
即,方法名相同,參數(shù)的個(gè)數(shù)或類型不同,返回值可以相同,也可以不同。
- 概述
重寫與重載是java多態(tài)性的具體表現(xiàn)形式.
??使用的原則是:相同的行為,表現(xiàn)形式不同時(shí)使用。
3.普通類、抽象類和接口的區(qū)別
普通類:
是具有一系列屬性和行為的類,它可以被實(shí)例化成一個(gè)對(duì)象。抽象類:
是普通類的抽象形式,它僅僅代表一個(gè)分類或抽象概念,它的實(shí)例化沒(méi)有任何意義,因此不希望它被實(shí)例化。即,抽象類并不是一個(gè)完整的對(duì)象。
特征:
1.抽象類使用abstract class對(duì)類名進(jìn)行標(biāo)記;
2.抽象類可以有抽象方法,也可以沒(méi)有抽象方法,其使用 abstract標(biāo)記;
3.抽象類不可以被實(shí)例化;
4.抽象類可以有普通方法,并實(shí)現(xiàn)具體行為。
5.抽象類的子類,必須實(shí)現(xiàn)父類的抽象方法,或者子類也是抽象類。
6.抽象類通過(guò)extends使用,一個(gè)類只能繼承一個(gè)抽象類。接口:
接口是特殊的抽象方法,在接口中所有的方法都是抽象方法。
特征:
1.接口使用interface對(duì)類名進(jìn)行標(biāo)記;
2.接口中全部都是抽象方法,不可以寫方法的實(shí)現(xiàn),由子類實(shí)現(xiàn)具體的行為;
3.接口不可以被實(shí)例化;
4.接口通過(guò)implements使用,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口。接口和抽象類的之間的區(qū)別。
1.變量,抽象類可以有實(shí)例變量,而接口不能擁有實(shí)例變量,接口中的變量都是靜態(tài)的常量。
2.方法,抽象類中可以有非抽象方法,而接口中只能擁有抽象方法。
3.接口可以多繼承,抽象類只能繼承一個(gè)。接口和抽象類的使用場(chǎng)景
在考慮使用抽象類還是使用接口時(shí),應(yīng)該從以下兩點(diǎn)出發(fā)。
1.父類中不需要實(shí)現(xiàn)具體的功能,使用接口;
2.子類需要繼承多個(gè)父類,才能實(shí)現(xiàn)完整的功能時(shí),使用接口;
其他情況,一般會(huì)使用抽象類。
參考鏈接
4.類的初始化流程
父類:
public class ClassA {
//構(gòu)造方法
ClassA() {
System.out.println("父類-構(gòu)造方法");
}
//非靜態(tài)代碼塊
{
System.out.println("父類-非靜態(tài)代碼塊");
}
//靜態(tài)代碼塊
static {
System.out.println("父類-靜態(tài)代碼塊");
}
//靜態(tài)方法
public static void mothedA() {
System.out.println("父類-靜態(tài)方法");
}
}
子類:
public class ClassB extends ClassA {
//構(gòu)造方法
ClassB() {
System.out.println("子類-構(gòu)造方法");
}
//非靜態(tài)代碼塊
{
System.out.println("子類-非靜態(tài)代碼塊");
}
//靜態(tài)代碼塊
static {
System.out.println("子類-靜態(tài)代碼塊");
}
//靜態(tài)方法
public static void mothedB() {
System.out.println("子類-靜態(tài)方法");
}
//靜態(tài)方法
public static void mothedA() {
System.out.println("父類-靜態(tài)方法");
}
}
備注:
1.父類的方法優(yōu)先與子類的方法;
2.同一個(gè)類中的非靜態(tài)代碼塊與構(gòu)造方法先后執(zhí)行,執(zhí)行完成后才會(huì)執(zhí)行到子類;
3.若直接調(diào)用靜態(tài)方法,優(yōu)先于非靜態(tài)代碼塊。
| 調(diào)用方式 | 執(zhí)行順序 |
|---|---|
| new ClassA(); | 父類-靜態(tài)代碼塊 子類-靜態(tài)代碼塊 父類-非靜態(tài)代碼塊 父類-構(gòu)造方法 |
| new ClassB(); | 父類-靜態(tài)代碼塊 子類-靜態(tài)代碼塊 父類-非靜態(tài)代碼塊 父類-構(gòu)造方法 子類-非靜態(tài)代碼塊 子類-構(gòu)造方法 |
| ClassA.mothedA(); | 父類-靜態(tài)代碼塊 子類-靜態(tài)代碼塊 父類-靜態(tài)方法 |
| ClassB.mothedA(); | 父類-靜態(tài)代碼塊 子類-靜態(tài)代碼塊 父類-靜態(tài)方法 |
| ClassB.mothedB(); | 父類-靜態(tài)代碼塊 子類-靜態(tài)代碼塊 子類-靜態(tài)方法 |
總結(jié):
1.直接調(diào)用靜態(tài)方法,即沒(méi)有實(shí)例化,不會(huì)運(yùn)行非靜態(tài)代碼塊和構(gòu)造方法;
2.同一個(gè)類中的非靜態(tài)代碼塊與構(gòu)造方法先后執(zhí)行,執(zhí)行完成后才會(huì)執(zhí)行到子類;
3.相同方法,父類優(yōu)先于子類;
以上是我對(duì)java象的簡(jiǎn)單理解。
若有問(wèn)題,歡迎指正、留言,歡迎大家一起討論。