@TOC
update time 2019年12月5日 13:45:47
CSDN地址 (csdn暫時(shí)有目錄更方便 查找閱讀 -沈跨。-)
虛擬機(jī) 基礎(chǔ)
JVM內(nèi)存管理
JVM執(zhí)行Java程序的過程:Java源代碼文件(.java)會(huì)被Java編譯器編譯為字節(jié)碼文件(.class),然后JVM中的類加載器加載各個(gè)類的字節(jié)碼文件兔综,加載完畢之后饿凛,交由JVM執(zhí)行引擎執(zhí)行。
運(yùn)行時(shí)數(shù)據(jù)區(qū)被分為 線程私有數(shù)據(jù)區(qū) 和 線程共享數(shù)據(jù)區(qū) 兩大類:
線程私有數(shù)據(jù)區(qū)包含:程序計(jì)數(shù)器软驰、虛擬機(jī)棧涧窒、本地方法棧
線程共享數(shù)據(jù)區(qū)包含:Java堆、方法區(qū)(內(nèi)部包含常量池)
線程私有數(shù)據(jù)區(qū)包含:
- 程序計(jì)數(shù)器:是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器
- 虛擬機(jī)棧:是Java方法執(zhí)行的內(nèi)存模型
- 本地方法棧:是虛擬機(jī)使用到的Native方法服務(wù)
線程共享數(shù)據(jù)區(qū)包含:
Java堆:用于存放幾乎所有的對(duì)象實(shí)例和數(shù)組锭亏;是垃圾收集器管理的主要區(qū)域纠吴,也被稱做“GC堆”;是Java虛擬機(jī)所管理的內(nèi)存中最大的一塊
方法區(qū):用于存儲(chǔ)已被虛擬機(jī)加載的類信息慧瘤、常量戴已、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)锅减;Class文件中除了有類的版本糖儡、字段、方法怔匣、接口等描述信息外握联,還有一項(xiàng)信息是常量池(Constant Pool Table),用于存放編譯期生成的各種字面量和符號(hào)引用,這部分內(nèi)容將在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放
Java堆和棧的區(qū)別
堆內(nèi)存
用于存儲(chǔ)Java中的對(duì)象和數(shù)組金闽,當(dāng)我們new一個(gè)對(duì)象或者創(chuàng)建一個(gè)數(shù)組的時(shí)候纯露,就會(huì)在堆內(nèi)存中開辟一段空間給它,用于存放代芜。特點(diǎn): 先進(jìn)先出埠褪,后進(jìn)后出。堆可以動(dòng)態(tài)地分配內(nèi)存大小蜒犯,由于要在運(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存组橄,存取速度較慢。棧內(nèi)存
主要是用來執(zhí)行程序用的罚随,比如:基本類型的變量和對(duì)象的引用變量玉工。特點(diǎn):先進(jìn)后出,后進(jìn)先出淘菩,存取速度比堆要快遵班,僅次于寄存器,棧數(shù)據(jù)可以共享潮改,但缺點(diǎn)是狭郑,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性
垃圾回收機(jī)制/ 回收算法
判定對(duì)象可回收有兩種方法:
引用計(jì)數(shù)算法:給對(duì)象中添加一個(gè)引用計(jì)數(shù)器汇在,每當(dāng)有一個(gè)地方引用它時(shí)翰萨,計(jì)數(shù)器值就加1;當(dāng)引用失效時(shí)糕殉,計(jì)數(shù)器值就減1亩鬼;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的。然而在主流的Java虛擬機(jī)里未選用引用計(jì)數(shù)算法來管理內(nèi)存阿蝶,主要原因是它難以解決對(duì)象之間相互循環(huán)引用的問題雳锋,所以出現(xiàn)了另一種對(duì)象存活判定算法。
可達(dá)性分析法:通過一系列被稱為『GC Roots』的對(duì)象作為起始點(diǎn)羡洁,從這些節(jié)點(diǎn)開始向下搜索玷过,搜索所走過的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒有任何引用鏈相連時(shí)筑煮,則證明此對(duì)象是不可用的辛蚊。其中可作為GC Roots的對(duì)象:虛擬機(jī)棧中引用的對(duì)象,主要是指棧幀中的本地變量真仲、本地方法棧中Native方法引用的對(duì)象嚼隘、方法區(qū)中類靜態(tài)屬性引用的對(duì)象、方法區(qū)中常量引用的對(duì)象
回收算法
分代收集算法:是當(dāng)前商業(yè)虛擬機(jī)都采用的一種算法袒餐,根據(jù)對(duì)象存活周期的不同飞蛹,將Java堆劃分為新生代和老年代谤狡,并根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?/p>
- 新生代:多數(shù)對(duì)象死去,少量存活卧檐。使用『復(fù)制算法』墓懂,只需復(fù)制少量存活對(duì)象即可。
- 復(fù)制算法:把可用內(nèi)存按容量劃分為大小相等的兩塊霉囚,每次只使用其中的一塊捕仔。當(dāng)這一塊的內(nèi)存用盡后,把還存活著的對(duì)象『復(fù)制』到另外一塊上面盈罐,再將這一塊內(nèi)存空間一次清理掉榜跌。
- 老年代:對(duì)象存活率高。使用『標(biāo)記—清理算法』或者『標(biāo)記—整理算法』盅粪,只需標(biāo)記較少的回收對(duì)象即可钓葫。
- 標(biāo)記-清除算法:首先『標(biāo)記』出所有需要回收的對(duì)象,然后統(tǒng)一『清除』所有被標(biāo)記的對(duì)象票顾。
- 標(biāo)記-整理算法:首先『標(biāo)記』出所有需要回收的對(duì)象础浮,然后進(jìn)行『整理』,使得存活的對(duì)象都向一端移動(dòng)奠骄,最后直接清理掉端邊界以外的內(nèi)存豆同。
Java基礎(chǔ)
Java 引用類型
強(qiáng)引用(StrongReference):具有強(qiáng)引用的對(duì)象不會(huì)被GC;即便內(nèi)存空間不足含鳞,JVM寧愿拋出OutOfMemoryError使程序異常終止影锈,也不會(huì)隨意回收具有強(qiáng)引用的對(duì)象。
軟引用(SoftReference):具有軟引用的對(duì)象蝉绷,會(huì)在內(nèi)存空間不足的時(shí)候被GC鸭廷;軟引用常用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存。
弱引用(WeakReference):被弱引用關(guān)聯(lián)的對(duì)象潜必,無論當(dāng)前內(nèi)存是否足夠都會(huì)被GC;強(qiáng)度比軟引用更弱沃但,常用于描述非必需對(duì)象磁滚;常用于解決內(nèi)存泄漏的問題(Handle 中Context 部分)
虛引用(PhantomReference):僅持有虛引用的對(duì)象,在任何時(shí)候都可能被GC宵晚;常用于跟蹤對(duì)象被GC回收的活動(dòng)垂攘;必須和引用隊(duì)列 (ReferenceQueue)聯(lián)合使用,當(dāng)垃圾回收器準(zhǔn)備回收一個(gè)對(duì)象時(shí)淤刃,如果發(fā)現(xiàn)它還有虛引用晒他,就會(huì)在回收對(duì)象的內(nèi)存之前,把這個(gè)虛引用加入到與之關(guān)聯(lián)的引用隊(duì)列中逸贾。
類加載機(jī)制
類加載機(jī)制:是虛擬機(jī)把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存陨仅,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)津滞、轉(zhuǎn)換解析和初始化,形成可被虛擬機(jī)直接使用的Java類型的過程灼伤。另外触徐,類型的加載、連接和初始化過程都是在程序運(yùn)行期完成的狐赡,從而通過犧牲一些性能開銷來換取Java程序的高度靈活性撞鹉。主要階段:
加載(Loading):通過類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流;將該二進(jìn)制字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)颖侄,該數(shù)據(jù)存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)由虛擬機(jī)實(shí)現(xiàn)自行定義鸟雏;在內(nèi)存中生成一個(gè)代表這個(gè)類的java.lang.Class對(duì)象,它將作為程序訪問方法區(qū)中的這些類型數(shù)據(jù)的外部接口
驗(yàn)證(Verification):確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求览祖,包括文件格式驗(yàn)證孝鹊、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證和符號(hào)引用驗(yàn)證
準(zhǔn)備(Preparation):為類變量分配內(nèi)存穴墅,因?yàn)檫@里的變量是由方法區(qū)分配內(nèi)存的惶室,所以僅包括類變量而不包括實(shí)例變量,后者將會(huì)在對(duì)象實(shí)例化時(shí)隨著對(duì)象一起分配在Java堆中玄货;設(shè)置類變量初始值皇钞,通常情況下零值
解析(Resolution):虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過程
初始化(Initialization):是類加載過程的最后一步,會(huì)開始真正執(zhí)行類中定義的Java字節(jié)碼松捉。而之前的類加載過程中夹界,除了在『加載』階段用戶應(yīng)用程序可通過自定義類加載器參與之外,其余階段均由虛擬機(jī)主導(dǎo)和控制
內(nèi)存模型
主內(nèi)存是所有變量的存儲(chǔ)位置隘世,每條線程都有自己的工作內(nèi)存可柿,用于保存被該線程使用到的變量的主內(nèi)存副本拷貝。為了獲取更好的運(yùn)行速度丙者,虛擬機(jī)可能會(huì)讓工作內(nèi)存優(yōu)先存儲(chǔ)于寄存器和高速緩存中复斥。
并發(fā)過程中的原子性 時(shí)序性
- 原子性
可直接保證的原子性變量操作有:read、load械媒、assign目锭、use、store和write纷捞,因此可認(rèn)為基本數(shù)據(jù)類型的訪問讀寫是具備原子性的痢虹。
若需要保證更大范圍的原子性,可通過更高層次的字節(jié)碼指令monitorenter和monitorexit來隱式地使用lock和unlock這兩個(gè)操作主儡,反映到Java代碼中就是同步代碼塊synchronized關(guān)鍵字奖唯。
- 可見性(一個(gè)線程修改了共享變量的值,其他線程能夠立即得知這個(gè)修改)
通過在變量修改后將新值同步回主內(nèi)存糜值,在變量讀取前從主內(nèi)存刷新變量值這種依賴主內(nèi)存作為傳遞媒介的方式來實(shí)現(xiàn)丰捷。
提供三個(gè)關(guān)鍵字保證可見性:volatile能保證新值能立即同步到主內(nèi)存坯墨,且每次使用前立即從主內(nèi)存刷新;synchronized對(duì)一個(gè)變量執(zhí)行unlock操作之前可以先把此變量同步回主內(nèi)存中瓢阴;被final修飾的字段在構(gòu)造器中一旦初始化完成且構(gòu)造器沒有把this的引用傳遞出去畅蹂,就可以在其他線程中就能看見final字段的值。
- 有序性(按照指令順序執(zhí)行)
如果在本線程內(nèi)觀察荣恐,所有的操作都是有序的液斜,指“線程內(nèi)表現(xiàn)為串行的語義”;如果在一個(gè)線程中觀察另一個(gè)線程叠穆,所有的操作都是無序的少漆,指“指令重排序”現(xiàn)象和“工作內(nèi)存與主內(nèi)存同步延遲”現(xiàn)象。
提供兩個(gè)關(guān)鍵字保證有序性:volatile 本身就包含了禁止指令重排序的語義硼被;synchronized保證一個(gè)變量在同一個(gè)時(shí)刻只允許一條線程對(duì)其進(jìn)行l(wèi)ock操作示损,使得持有同一個(gè)鎖的兩個(gè)同步塊只能串行地進(jìn)入。
設(shè)計(jì)模式 (使用過的)
單一職責(zé)原則:一個(gè)類只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)
開放封閉原則:對(duì)擴(kuò)展開放嚷硫,對(duì)修改關(guān)閉
依賴倒置原則:抽象不應(yīng)該依賴于細(xì)節(jié)检访,細(xì)節(jié)應(yīng)當(dāng)依賴于抽象。換言之仔掸,要針對(duì)接口編程脆贵,而不是針對(duì)實(shí)現(xiàn)編程
迪米特法則:應(yīng)該盡量減少對(duì)象之間的交互,如果兩個(gè)對(duì)象之間不必彼此直接通信起暮,那么這兩個(gè)對(duì)象就不應(yīng)當(dāng)發(fā)生任何直接的相互作用卖氨,如果其中的一個(gè)對(duì)象需要調(diào)用另一個(gè)對(duì)象的某一個(gè)方法的話,可以通過第三者轉(zhuǎn)發(fā)這個(gè)調(diào)用
合成/聚合復(fù)用原則:要盡量使用合成/聚合负懦,盡量不要使用繼承
延伸:Android 中源碼使用的設(shè)計(jì)模式筒捺,自己使用過的設(shè)計(jì)模式
View事件分發(fā): 責(zé)任鏈模式
BitmapFactory加載圖片: 工廠模式
ListAdapter: 適配器模式
DialogBuilder: 建造者模式
Adapter.notifyDataSetChanged(): 觀察者模式
Binder機(jī)制: 代理模式
平時(shí)經(jīng)常使用的 設(shè)計(jì)模式
單例模式
初級(jí)版
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
進(jìn)階版
public class Singleton {
private volatile static Singleton singleton;//代碼1
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {//代碼2
synchronized (Singleton.class) {
if (singleton == null) {//代碼3
singleton = new Singleton();//代碼4
}
}
}
return singleton;
}
}
??在多線程中 兩個(gè)線程可能同時(shí)進(jìn)入代碼2, synchronize保證只有一個(gè)線程能進(jìn)入下面的代碼,
??此時(shí)一個(gè)線程A進(jìn)入一個(gè)線程B在外等待, 當(dāng)線程A完成代碼3 和代碼4之后,
線程B進(jìn)入synchronized下面的方法, 線程B在代碼3的時(shí)候判斷不過,從而保證了多線程下 單例模式的線程安全,
??另外要慎用單例模式,因?yàn)閱卫J揭坏┏跏蓟?只有進(jìn)程退出才有可能被回收,如果一個(gè)對(duì)象不經(jīng)常被使用,盡量不要使用單例,否則為了幾次使用,一直讓單例存在占用內(nèi)存
優(yōu)點(diǎn):
- 內(nèi)存中只存在一個(gè)對(duì)象,節(jié)省了系統(tǒng)資源纸厉。
- 避免對(duì)資源的多重占用系吭,例如一個(gè)文件操作,由于只有一個(gè)實(shí)例存在內(nèi)存中颗品,避免對(duì)同一資源文件的同時(shí)操作肯尺。
缺點(diǎn):
- 單例對(duì)象如果持有Context,那么很容易引發(fā)內(nèi)存泄露抛猫。
- 單例模式一般沒有接口蟆盹,擴(kuò)展很困難孩灯,若要擴(kuò)展闺金,只能修改代碼來實(shí)現(xiàn)。
Builder 模式
具體的產(chǎn)品類
public class Computer {
private String mCPU;
private String mMemory;
private String mHD;
public void setCPU(String CPU) {
mCPU = CPU;
}
public void setMemory(String memory) {
mMemory = memory;
}
public void setHD(String HD) {
mHD = HD;
}
}
抽象建造者
public abstract class Builder {
public abstract void buildCPU(String cpu);//組裝CPU
public abstract void buildMemory(String memory);//組裝內(nèi)存
public abstract void buildHD(String hd);//組裝硬盤
public abstract Computer create();//返回組裝好的電腦
}
創(chuàng)建者實(shí)現(xiàn)類
public class ConcreteBuilder extends Builder {
//創(chuàng)建產(chǎn)品實(shí)例
private Computer mComputer = new Computer();
@Override
public void buildCPU(String cpu) {//組裝CPU
mComputer.setCPU(cpu);
}
@Override
public void buildMemory(String memory) {//組裝內(nèi)存
mComputer.setMemory(memory);
}
@Override
public void buildHD(String hd) {//組裝硬盤
mComputer.setHD(hd);
}
@Override
public Computer create() {//返回組裝好的電腦
return mComputer;
}
}
調(diào)用者
public class Director {
private Builder mBuild = null;
public Director(Builder build) {
this.mBuild = build;
}
//指揮裝機(jī)人員組裝電腦
public void Construct(String cpu, String memory, String hd) {
mBuild.buildCPU(cpu);
mBuild.buildMemory(memory);
mBuild.buildHD(hd);
}
}
調(diào)用
Director direcror = new Director(new ConcreteBuilder());//創(chuàng)建指揮者實(shí)例峰档,并分配相應(yīng)的建造者败匹,(老板分配任務(wù))
direcror.Construct("i7-6700", "三星DDR4", "希捷1T");//組裝電腦
Builder 模式 優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 封裝性良好寨昙,隱藏內(nèi)部構(gòu)建細(xì)節(jié)。
- 易于解耦掀亩,將產(chǎn)品本身與產(chǎn)品創(chuàng)建過程進(jìn)行解耦舔哪,可以使用相同的創(chuàng)建過程來得到不同的產(chǎn)品。也就說細(xì)節(jié)依賴抽象槽棍。
- 易于擴(kuò)展捉蚤,具體的建造者類之間相互獨(dú)立,增加新的具體建造者無需修改原有類庫的代碼炼七。
- 易于精確控制對(duì)象的創(chuàng)建缆巧,由于具體的建造者是獨(dú)立的,因此可以對(duì)建造過程逐步細(xì)化豌拙,而不對(duì)其他的模塊產(chǎn)生任何影響陕悬。
缺點(diǎn)
- 產(chǎn)生多余的Build對(duì)象以及Dirextor類。
- 建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點(diǎn)按傅,其組成部分相似捉超;如果產(chǎn)品之間的差異性很大,則不適合使用建造者模式唯绍,因此其使用范圍受到一定的限制
源碼中使用的 比如: Dialog.Builder
工廠模式
抽象產(chǎn)品類
public abstract class Product {
public abstract void show();
}
具體產(chǎn)品類
public class ProductA extends Product {
@Override
public void show() {
System.out.println("product A");
}
}
//具體產(chǎn)品類B
public class ProductB extends Product {
@Override
public void show() {
System.out.println("product B");
}
}
創(chuàng)建抽象工廠類
//抽象工廠類
public abstract class Factory {
public abstract Product create();
}
創(chuàng)建具體工廠類拼岳,繼承抽象工廠類
public class FactoryA extends Factory {
@Override
public Product create() {
return new ProductA();//創(chuàng)建ProductA
}
}
//具體工廠類B
public class FactoryB extends Factory {
@Override
public Product create() {
return new ProductB();//創(chuàng)建ProductB
}
}
測(cè)試代碼
Factory factoryA = new FactoryA();
Product productA = factoryA.create();
productA.show();
//產(chǎn)品B
Factory factoryB = new FactoryB();
Product productB = factoryB.create();
productB.show();
優(yōu)點(diǎn):
- 符合開放封閉原則。新增產(chǎn)品時(shí)推捐,只需增加相應(yīng)的具體產(chǎn)品類和相應(yīng)的工廠子類即可裂问。
- 符合單一職責(zé)原則。每個(gè)具體工廠類只負(fù)責(zé)創(chuàng)建對(duì)應(yīng)的產(chǎn)品牛柒。
缺點(diǎn):
- 增加新產(chǎn)品時(shí)堪簿,還需增加相應(yīng)的工廠類,系統(tǒng)類的個(gè)數(shù)將成對(duì)增加皮壁,增加了系統(tǒng)的復(fù)雜度和性能開銷椭更。
源碼中 使用的 比如 ThreadFactory
觀察者模式
含義: 定義對(duì)象間的一種一個(gè)對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)送改變時(shí)蛾魄,所以依賴于它的對(duì)象都得到通知并被自動(dòng)更新虑瀑。
備注:
Subject(抽象主題):又叫抽象被觀察者,把所有觀察者對(duì)象的引用保存到一個(gè)集合里滴须,每個(gè)主題都可以有任何數(shù)量的觀察者舌狗。抽象主題提供一個(gè)接口,可以增加和刪除觀察者對(duì)象扔水。
ConcreteSubject(具體主題):又叫具體被觀察者痛侍,將有關(guān)狀態(tài)存入具體觀察者對(duì)象;在具體主題內(nèi)部狀態(tài)改變時(shí)魔市,給所有登記過的觀察者發(fā)出通知主届。
Observer (抽象觀察者):為所有的具體觀察者定義一個(gè)接口赵哲,在得到主題通知時(shí)更新自己。
ConcrereObserver(具體觀察者):實(shí)現(xiàn)抽象觀察者定義的更新接口君丁,當(dāng)?shù)玫街黝}更改通知時(shí)更新自身的狀態(tài)枫夺。
代碼實(shí)現(xiàn)
抽象觀察者
public interface Observer {//抽象觀察者
public void update(String message);//更新方法
}
具體觀察者
public class Boy implements Observer {
private String name;//名字
public Boy(String name) {
this.name = name;
}
@Override
public void update(String message) {//男孩的具體反應(yīng)
System.out.println(name + ",收到了信息:" + message+"屁顛顛的去取快遞.");
}
}
創(chuàng)建抽象主題
public interface Observable {//抽象被觀察者
void add(Observer observer);//添加觀察者
void remove(Observer observer);//刪除觀察者
void notify(String message);//通知觀察者
}
創(chuàng)建具體主題
public class Postman implements Observable{//快遞員
private List<Observer> personList = new ArrayList<Observer>();//保存收件人(觀察者)的信息
@Override
public void add(Observer observer) {//添加收件人
personList.add(observer);
}
@Override
public void remove(Observer observer) {//移除收件人
personList.remove(observer);
}
@Override
public void notify(String message) {//逐一通知收件人(觀察者)
for (Observer observer : personList) {
observer.update(message);
}
}
}
測(cè)試代碼
Observable postman=new Postman();
Observer boy1=new Boy("路飛");
Observer boy2=new Boy("喬巴");
postman.notify("快遞到了,請(qǐng)下樓領(lǐng)取.");
優(yōu)點(diǎn):
- 解除觀察者與主題之間的耦合。讓耦合的雙方都依賴于抽象绘闷,而不是依賴具體橡庞。從而使得各自的變化都不會(huì)影響另一邊的變化。
- 易于擴(kuò)展印蔗,對(duì)同一主題新增觀察者時(shí)無需修改原有代碼毙死。
缺點(diǎn):
- 使用觀察者模式時(shí)需要考慮一下開發(fā)效率和運(yùn)行效率的問題,程序中包括一個(gè)被觀察者喻鳄、多個(gè)觀察者扼倘,開發(fā)、調(diào)試等內(nèi)容會(huì)比較復(fù)雜除呵,而且在Java中消息的通知一般是順序執(zhí)行再菊,那么一個(gè)觀察者卡頓,會(huì)影響整體的執(zhí)行效率颜曾,在這種情況下纠拔,一般會(huì)采用異步實(shí)現(xiàn)。
- 可能會(huì)引起多余的數(shù)據(jù)通知泛豪。
Android 源碼中的觀察者模式:Listener
其他設(shè)計(jì)模式
由于本人涉獵較少稠诲,有些只能說簡(jiǎn)單了解。這里分享一個(gè) 不錯(cuò)的 系列博客诡曙,感謝前人栽樹臀叙。
源碼設(shè)計(jì)
接口和抽象類
- 抽象類可以提供成員方法的實(shí)現(xiàn)細(xì)節(jié),而接口中只能存在 public 抽象方法,沒有實(shí)現(xiàn)慎璧,(JDK8以后可以有)
- 抽象類中的成員變量可以是各種類型的床嫌,而接口中的成員變量只能是 public static final 類型的;
- 接口的成員變量只能是靜態(tài)常量胸私,沒有構(gòu)造函數(shù)厌处,也沒有代碼塊,但抽象類都可以有岁疼。
- 一個(gè)類只能繼承一個(gè)抽象類阔涉,而一個(gè)類卻可以實(shí)現(xiàn)多個(gè)接口;
抽象類訪問速度比接口速度要快,因?yàn)榻涌谛枰獣r(shí)間去尋找在類中具體實(shí)現(xiàn)的方法洒敏; - 如果你往抽象類中添加新的方法,你可以給它提供默認(rèn)的實(shí)現(xiàn)疙驾。因此你不需要改變你現(xiàn)在的代碼凶伙。如果你往接口中添加方法,那么你必須改變實(shí)現(xiàn)該接口的類它碎。
所以:抽象類強(qiáng)調(diào)的是重用函荣,接口強(qiáng)調(diào)的是解耦。
最后更新時(shí)間:2019年12月5日 13:45:40