日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747



1、Struts2和SpringMVC的區(qū)別

 

(1)設(shè)計(jì)理念:前者為有狀態(tài)的Action(均為多例),Action對(duì)象屬性字段承載請(qǐng)求、響應(yīng),后者一般為無(wú)狀態(tài)的Controller,請(qǐng)求直接封裝到方法的參數(shù)中;

(2)集中訪問(wèn)點(diǎn)不同:都屬于前端控制器,用于接收請(qǐng)求、處理請(qǐng)求和生成響應(yīng),但集中訪問(wèn)點(diǎn)不同,前者為Filter,后者為Servlet;

(3)請(qǐng)求處理粒度不同:前者一個(gè)Action對(duì)應(yīng)一個(gè)請(qǐng)求上下文,后者一個(gè)方法對(duì)應(yīng)一個(gè)請(qǐng)求上下文,因此更容易實(shí)現(xiàn)Rest;

(4)攔截器機(jī)制不同:Struts2和SpringMVC的攔截器機(jī)制均是對(duì)AOP理念的應(yīng)用,但Struts2的interceptor機(jī)制是通過(guò)代理機(jī)制(ActionProxy)+責(zé)任鏈模式實(shí)現(xiàn)的,而SpringMVC的interceptor機(jī)制實(shí)現(xiàn)比較簡(jiǎn)單,其通過(guò)循環(huán)的方式在handler處理請(qǐng)求前后分別調(diào)用preHandle()方法和postHandle()方法對(duì)請(qǐng)求和響應(yīng)進(jìn)行處理,與Spring AOP、責(zé)任鏈模式等基本無(wú)關(guān);

(5)對(duì)ajax的支持不同:前者需要插件或者手動(dòng)轉(zhuǎn)化,而后者集成了對(duì)Ajax請(qǐng)求的處理(HttpMessageConverter);

(6)與Spring的整合:前者需要插件,后者無(wú)縫整合(子容器);

(7)配置/效率:后者幾乎是零配置,開發(fā)效率更高。

2、Spring中IOC的理解

(1)超級(jí)大工廠:對(duì)象控制權(quán)由調(diào)用者移交給容器,使得調(diào)用者不必關(guān)心對(duì)象的創(chuàng)建和管理,專注于業(yè)務(wù)邏輯開發(fā);

(2)優(yōu)秀的解耦方式,解耦對(duì)象間的依賴關(guān)系,避免通過(guò)硬編碼的方式耦合在一起;

(3)底層實(shí)現(xiàn):反射機(jī)制;

3、Spring中AOP的理解

 

(1)一種新的模塊化方式,專門處理系統(tǒng)各模塊中的交叉關(guān)注點(diǎn)問(wèn)題,將具有橫切性質(zhì)的系統(tǒng)級(jí)業(yè)務(wù)提取到切面中,與核心業(yè)務(wù)邏輯分離(解耦);

(2)便于系統(tǒng)的擴(kuò)展,符合開-閉原則;

(3)動(dòng)態(tài)AOP的實(shí)現(xiàn),JAVA動(dòng)態(tài)代理(接口代理)cglib(類代理),具體由Bean后處理器生成代理;

(4)AOP理念實(shí)踐:Spring AOP,Java Web Filter,Struts2 Interceptor, SpringMVC Interceptor,…

4、JVM 基礎(chǔ)

 

4.1內(nèi)存模型

 

(1)程序計(jì)數(shù)器:線程私有,CPU調(diào)度的基本單位,用于保證線程切換(程序能夠在多線程環(huán)境下連續(xù)執(zhí)行);

(2)(服務(wù)Java方法虛擬機(jī)棧、服務(wù)Native方法的本地方法棧):線程私有,局部變量/引用,棧深度(SOF)/無(wú)法申請(qǐng)內(nèi)存(OOM);

(3)(Java代碼可及的Java堆和JVM自身使用的方法區(qū)):線程共享,對(duì)象分配和回收主要區(qū)域,OOM;

4.2垃圾回收機(jī)制

 

(1)Stop-the-World

JVM由于要執(zhí)行GC而停止了應(yīng)用程序的執(zhí)行稱之為Stop-the-World,該情形會(huì)在任何一種GC算法中發(fā)生。當(dāng)Stop-the-world發(fā)生時(shí),除了GC所需的線程以外,所有線程都處于等待狀態(tài)直到GC任務(wù)完成。事實(shí)上,GC優(yōu)化很多時(shí)候就是指減少Stop-the-world發(fā)生的時(shí)間,從而使系統(tǒng)具有高吞吐 、低停頓的特點(diǎn)。

(2)JAVA堆的回收

關(guān)于Java對(duì)象的回收主要考慮以下兩個(gè)問(wèn)題:哪些對(duì)象可以被回收、怎么回收(有哪些回收算法以及有哪些垃圾回收器)。

①判斷對(duì)象是否可被回收:引用計(jì)數(shù)法(相互引用)、可達(dá)性算法(對(duì)象的引用鏈?zhǔn)欠窨蛇_(dá),GCRoots)

②垃圾回收算法:標(biāo)記-清除算法(內(nèi)存碎片)、復(fù)制算法(垃圾回收較為頻繁、對(duì)象存活率較低的新生代)、標(biāo)記-整理算法(垃圾回收不頻繁、對(duì)象存活率較高的老年代)、分代收集算法。

垃圾回收器:串行收集器(新生代、老年代)、并行收集器(新生代、老年代)、并行清除收集器(并發(fā),新生代,追求高吞吐)、CMS收集器(并發(fā),老年代,標(biāo)記-清除算法,追求低停頓)、G1垃圾收集器(整個(gè)堆,追求低停頓)

附:

GC Roots一般包括虛擬機(jī)棧中引用的對(duì)象,本地方法棧中引用的對(duì)象,方法區(qū)中類靜態(tài)屬性引用的對(duì)象、方法區(qū)中常量引用的對(duì)象。

附:

GC Roots一般包括虛擬機(jī)棧中引用的對(duì)象,本地方法棧中引用的對(duì)象,方法區(qū)中類靜態(tài)屬性引用的對(duì)象、方法區(qū)中常量引用的對(duì)象。

分代收集算法的基本思想是:不同的對(duì)象的生命周期(存活情況)是不一樣的,而不同生命周期的對(duì)象位于堆中不同的區(qū)域,因此對(duì)堆內(nèi)存不同區(qū)域采用不同的策略進(jìn)行回收可以提高 JVM 的執(zhí)行效率。Minor GC 發(fā)生頻率較高,不一定等 Eden區(qū)滿了才觸發(fā);Major GC在老年代滿時(shí)觸發(fā),對(duì)年輕代和老年代進(jìn)行回收。

(3)方法區(qū)回收

①對(duì)常量池的回收。

②對(duì)類型的卸載:該類的所有實(shí)例被回收,該類的ClassLoader被回收,不存在對(duì)該類的Class對(duì)象的引用。

4.3 OOM/SOF

(1)OOM for Heap:內(nèi)存泄露(GC Roots的引用鏈,對(duì)象的生命周期超出預(yù)期)或者內(nèi)存溢出(調(diào)節(jié)JVM參數(shù) -Xms,-Xmx 等)

(2)OOM for Stack:一般在單線程程序中不會(huì)出現(xiàn);在多線程環(huán)境下,無(wú)法申請(qǐng)到足夠的內(nèi)存去創(chuàng)建線程

(3)SOF for Stack:程序是否有深度遞歸。

(4)OOM for Perm :用到像Spring等框架的時(shí)候,常常會(huì)動(dòng)態(tài)地生成大量的類導(dǎo)致永久代不夠用而導(dǎo)致OutOfMemoryError: PermGen Space異常(調(diào)大 -XX:MaxPermSize)

5、JVM 調(diào)優(yōu)

JVM 調(diào)優(yōu)的主要目標(biāo)是使系統(tǒng)具有高吞吐、低停頓的特點(diǎn),其優(yōu)化手段應(yīng)從兩方面著手:Java虛擬機(jī)和Java應(yīng)用程序。前者指根據(jù)應(yīng)用程序的設(shè)計(jì)通過(guò)虛擬機(jī)參數(shù)控制虛擬機(jī)邏輯內(nèi)存分區(qū)的大小以使虛擬機(jī)的內(nèi)存與程序?qū)?nèi)存的需求相得益彰;后者指優(yōu)化程序算法,降低GC負(fù)擔(dān),提高GC回收成功率。以下是一些常用的JVM調(diào)優(yōu)工具:

(1)Jconsole 與 Visual VM

JConsole 與 Visual VM 都是JDK自帶的 Java 性能分析器,可以從命令行或在 GUI shell 中運(yùn)行,從而可以輕松使用 JConsole來(lái)監(jiān)控 Java 應(yīng)用程序性能和跟蹤 Java 中的代碼,其可以從JAVA_HOME/bin/這個(gè)目錄下找到。使用 Jconsole 監(jiān)測(cè)死鎖示例如下:

Java知識(shí)點(diǎn)梳理

 

(1)Jstack

JDK自帶的命令行工具,可以查看某個(gè)Java進(jìn)程內(nèi)的線程堆棧信息,主要用于線程Dump分析。

Java知識(shí)點(diǎn)梳理

 

(1)JPS

jps位于jdk的bin目錄下,其作用是顯示當(dāng)前系統(tǒng)的java進(jìn)程情況及其id。

Java知識(shí)點(diǎn)梳理

 

6、責(zé)任鏈(CoR)模式

 

目的:請(qǐng)求的發(fā)送者與請(qǐng)求的處理者解耦,便于動(dòng)態(tài)的重新組織鏈和分配責(zé)任。

角色:抽象處理者、具體處理者、客戶端。

UML:

Java知識(shí)點(diǎn)梳理

 

傳統(tǒng)責(zé)任鏈(CoR)模式的缺點(diǎn)在于:具體處理角色存在著共同的實(shí)現(xiàn)責(zé)任鏈結(jié)構(gòu)的行為行為,即責(zé)任鏈的建立和指派包含在實(shí)現(xiàn)角色的類中,并沒有抽象出來(lái),這直接導(dǎo)致責(zé)任鏈的指派不夠靈活。因此,改進(jìn)的CoR模式為:使用AOP理念將責(zé)任鏈結(jié)構(gòu)的實(shí)現(xiàn)用切面抽象出來(lái),使得各個(gè)對(duì)象只關(guān)注自身必須實(shí)現(xiàn)的功能性需求,準(zhǔn)確地分離出責(zé)任鏈模式中不同角色的共同行為,例如,

Java知識(shí)點(diǎn)梳理

 

 

 

改進(jìn)后責(zé)任鏈(CoR)模式的應(yīng)用是比較廣泛的,包括 Java Web Filter(鏈?zhǔn)秸{(diào)用),Struts2 Interceptor(Action代理)和SpringMVC等。

7、單例模式

單例模式核心在于為整個(gè)系統(tǒng)提供一個(gè)唯一的實(shí)例,為整個(gè)系統(tǒng)提供一個(gè)全局訪問(wèn)點(diǎn)。單例模式從實(shí)現(xiàn)上可以分為餓漢式單例懶漢式單例兩種,前者天生就是線程安全的,后者則需要考慮線程安全性,常見的線程安全的懶漢式單例的實(shí)現(xiàn)有內(nèi)部類式和雙重檢查式兩種。下面給出單例模式幾種常見的形式:

 

(1) 餓漢式單例

Java知識(shí)點(diǎn)梳理

 

(1) 懶漢式單例

Java知識(shí)點(diǎn)梳理

 

 

 

(1) 線程安全的懶漢式單例 —— 內(nèi)部類方式

Java知識(shí)點(diǎn)梳理

 

內(nèi)部類方式線程安全懶漢式單例的內(nèi)在原理在于:虛擬機(jī)會(huì)保證一個(gè)類的類構(gòu)造器<clinit>()在多線程環(huán)境中被正確的加鎖、同步,如果多個(gè)線程同時(shí)去初始化一個(gè)類,那么只會(huì)有一個(gè)線程去執(zhí)行這個(gè)類的類構(gòu)造器<clinit>(),其他線程都需要阻塞等待,直到活動(dòng)線程執(zhí)行<clinit>()方法完畢。特別需要注意的是,在這種情形下,其他線程雖然會(huì)被阻塞,但如果執(zhí)行<clinit>()方法的那條線程退出后,其他線程在喚醒之后不會(huì)再次進(jìn)入/執(zhí)行<clinit>()方法,因?yàn)樵谕粋€(gè)類加載器下,一個(gè)類型只會(huì)被初始化一次。

(4) 線程安全的懶漢式單例——雙重檢查方式

Java知識(shí)點(diǎn)梳理

 

8、類的生命周期及其初始化時(shí)機(jī)

 

類的生命周期主要包括加載、鏈接、初始化、使用和卸載五個(gè)階段,如下圖所示:

Java知識(shí)點(diǎn)梳理

 

 

 

(1) 遇到new、getstatic、putstatic或invokestatic這四條字節(jié)碼指令時(shí):注意,newarray指令觸發(fā)的只是數(shù)組類型本身的初始化,而不會(huì)導(dǎo)致其相關(guān)類型的初始化,比如,new String[]只會(huì)直接觸發(fā)String[]類的初始化,也就是觸發(fā)對(duì)類[Ljava.lang.String的初始化,而直接不會(huì)觸發(fā)String類的初始化時(shí),如果類沒有進(jìn)行過(guò)初始化,則需要先對(duì)其進(jìn)行初始化。生成這四條指令的最常見的Java代碼場(chǎng)景是:

①使用new關(guān)鍵字實(shí)例化對(duì)象的時(shí)候;②讀取或設(shè)置一個(gè)類的靜態(tài)字段(被final修飾,已在編譯器把結(jié)果放入常量池的靜態(tài)字段除外)的時(shí)候;③調(diào)用一個(gè)類的靜態(tài)方法的時(shí)候。

(2) 對(duì)類進(jìn)行反射調(diào)用時(shí):使用java.lang.reflect包的方法對(duì)類進(jìn)行反射調(diào)用的時(shí)候,如果類沒有進(jìn)行過(guò)初始化,則需要先觸發(fā)其初始化。

 

(3) 初始化子類時(shí):當(dāng)初始

Java知識(shí)點(diǎn)梳理

 

化一個(gè)類

Java知識(shí)點(diǎn)梳理

 

時(shí)候,如果發(fā)現(xiàn)其父類還沒有進(jìn)行過(guò)初始化,則需要先觸發(fā)其父類的初始化。

(4) 虛擬機(jī)啟動(dòng)時(shí):當(dāng)虛擬機(jī)啟動(dòng)時(shí),用戶需要指定一個(gè)要執(zhí)行的主類(包含main()方法的那個(gè)類),虛擬機(jī)會(huì)先初始化這個(gè)主類。

(5) 當(dāng)使用jdk1.7動(dòng)態(tài)語(yǔ)言支持時(shí),如果一個(gè)java.lang.invoke.MethodHandle實(shí)例最后的解析結(jié)果REF_getstatic,REF_putstatic,REF_invokeStatic的方法句柄,并且這個(gè)方法句柄所對(duì)應(yīng)的類沒有進(jìn)行初始化,則需要先出觸發(fā)其初始化。

9、類加載過(guò)程中各階段的作用

 

9.1加載(Loading)

(1)通過(guò)一個(gè)類的全限定名來(lái)獲取定義此類的二進(jìn)制字節(jié)流(并沒有指明要從一個(gè)Class文件中獲取,可以從其他渠道,譬如:網(wǎng)絡(luò)、動(dòng)態(tài)生成、數(shù)據(jù)庫(kù)等);

(2)將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)

(3)在內(nèi)存中(對(duì)于HotSpot虛擬機(jī)而言就是方法區(qū))生成一個(gè)代表這個(gè)類的java.lang.Class對(duì)象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問(wèn)入口;

9.2鏈接(Linking)

(1)驗(yàn)證:驗(yàn)證是連接階段的第一步,這一階段的目的是為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)自身的安全。

(2)準(zhǔn)備(Preparation):準(zhǔn)備階段是正式為類變量(static 成員變量)分配內(nèi)存并設(shè)置類變量初始值(零值)的階段,這些變量所使用的內(nèi)存都將在方法區(qū)中進(jìn)行分配。

(3)解析(Resolution):解析階段是虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程。

9.3初始化

初始化階段是執(zhí)行類構(gòu)造器<clinit>()方法的過(guò)程。虛擬機(jī)會(huì)保證一個(gè)類的類構(gòu)造器<clinit>()在多線程環(huán)境中被正確的加鎖、同步,如果多個(gè)線程同時(shí)去初始化一個(gè)類,那么只會(huì)有一個(gè)線程去執(zhí)行這個(gè)類的類構(gòu)造器<clinit>(),其他線程都需要阻塞等待,直到活動(dòng)線程執(zhí)行<clinit>()方法完畢。特別需要注意的是,在這種情形下,其他線程雖然會(huì)被阻塞,但如果執(zhí)行<clinit>()方法的那條線程退出后,其他線程在喚醒之后不會(huì)再次進(jìn)入/執(zhí)行<clinit>()方法,因?yàn)樵?strong>同一個(gè)類加載器下,一個(gè)類型只會(huì)被初始化一次。

 

10、對(duì)象的創(chuàng)建過(guò)程

在Java中,創(chuàng)建一個(gè)對(duì)象常常需要經(jīng)歷如下幾個(gè)過(guò)程:父類的類構(gòu)造器<clinit>() -> 子類的類構(gòu)造器<clinit>() -> 父類的實(shí)例構(gòu)造器(成員變量和實(shí)例代碼塊,父類的構(gòu)造函數(shù)) -> 子類的實(shí)例構(gòu)造器(成員變量和實(shí)例代碼塊,子類的構(gòu)造函數(shù))。其中,類構(gòu)造器<clinit>()由靜態(tài)變量和靜態(tài)語(yǔ)句塊組成,而類的實(shí)例構(gòu)造器<init>()類的實(shí)例變量/語(yǔ)句塊以及其構(gòu)造函數(shù)組成。

11、雙親委派模型

雙親委派模型很好地解決了類加載器的統(tǒng)一加載問(wèn)題:越基礎(chǔ)的類由越上層的加載器進(jìn)行加載,進(jìn)而保證Java類型體系中最基礎(chǔ)的行為,防止應(yīng)用程序變得混亂。比如,java.lang.Object 類總是由啟動(dòng)類加載器進(jìn)行加載,因此Object類在程序的各種類加載器環(huán)境中都是同一個(gè)類型(是否是同一類型由類加載器與類本身共同決定)。

Java知識(shí)點(diǎn)梳理

 


Java知識(shí)點(diǎn)梳理

 

(1)BootStrap:引導(dǎo)類加載器:加載都是最基礎(chǔ)的文(JRE/lib/rt.jar)

(2)ExtClassLoader:引導(dǎo)類加載器:加載都是最基礎(chǔ)的文件(JRE/lib/ext/*.jar)

(3)AppClassLoader:ClassPath指定的所有jar或目錄。

12、異常機(jī)制

Java體系中異常的組織分類如下圖所示,所有異常類型的根類為 Throwable,具體包括兩大類:Error 與 Exception。其中,Error是指程序無(wú)法處理的錯(cuò)誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問(wèn)題;Exception是指程序本身可以處理的錯(cuò)誤,具體可分為運(yùn)行時(shí)異常(派生于 RuntimeException 的異常)和其他異常。

 

此外,從異常是否必須需要被處理的角度來(lái)看,異常又可分為不受檢查異常和受檢查異常兩種情況:

(1)不受檢查異常:派生于 Error 或 RuntimeException 的所有異常。

(2)受檢查異常:除去不受檢查異常的所有異常。

Java知識(shí)點(diǎn)梳理

 

finally子句,在對(duì)應(yīng)的try子句執(zhí)行的前提下,finally 子句總會(huì)被執(zhí)行。并且,finally子句 總是在諸如return、break、throw和continue等控制轉(zhuǎn)移語(yǔ)句之前執(zhí)行。

Java知識(shí)點(diǎn)梳理

 


Java知識(shí)點(diǎn)梳理

 


Java知識(shí)點(diǎn)梳理

 

13、六大設(shè)計(jì)原則

(1)單一職責(zé)原則:高內(nèi)聚,一個(gè)類只做它該做的事情;

(2)接口隔離原則:接口小而專,避免大而全;

(3)依賴倒置原則:依賴抽象而非實(shí)現(xiàn),面向接口編程;

(4)里氏替換原則:子類可以擴(kuò)展父類的功能,但不能改變父類原有的功能;

(5)開閉原則:Open for Extension, Closed for Modification,例如AOP,代理模式,適配器模式就是其經(jīng)典應(yīng)用;

(6)迪米特法則:高內(nèi)聚,低耦合;

14、代理模式

 

根據(jù)代理類的創(chuàng)建時(shí)機(jī)和創(chuàng)建方式的不同,我們可以將代理模式分為靜態(tài)代理和動(dòng)態(tài)代理兩種形式,其中,在程序運(yùn)行前就已經(jīng)存在的編譯好的代理類是為靜態(tài)代理,在程序運(yùn)行期間根據(jù)需要?jiǎng)討B(tài)的創(chuàng)建代理類及其實(shí)例來(lái)完成具體的功能是為動(dòng)態(tài)代理。其中,代理對(duì)象的作用如下:

(1) 代理對(duì)象存在的價(jià)值主要用于攔截對(duì)真實(shí)業(yè)務(wù)對(duì)象的訪問(wèn)

(2) 代理對(duì)象應(yīng)該具有和目標(biāo)對(duì)象(真實(shí)業(yè)務(wù)對(duì)象)相同的方法,即實(shí)現(xiàn)共同的接口或繼承于同一個(gè)類;

(3) 代理對(duì)象應(yīng)該是目標(biāo)對(duì)象的增強(qiáng),否則我們就沒有必要使用代理了。

Java知識(shí)點(diǎn)梳理

 

JDK 動(dòng)態(tài)代理是動(dòng)態(tài)代理模式的經(jīng)典實(shí)現(xiàn),主要包括三個(gè)角色對(duì)象:Subject (接口)、被代理的類以及InvocationHandler接口(一般持有被代理對(duì)象),例如:

(1)實(shí)現(xiàn) InvocationHandler 接口

Java知識(shí)點(diǎn)梳理

 

(2)Proxy.newProxyInstance

Java知識(shí)點(diǎn)梳理

 

但是,JDK動(dòng)態(tài)代理只能完成對(duì)接口的代理,而不能完成對(duì)類的代理,關(guān)鍵原因?yàn)椋?strong>Java只允許單繼承。具體地,代理對(duì)象proxySubject的類型為“com.sun.proxy.$Proxy0”,這恰好印證了proxySubject對(duì)象是一個(gè)代理對(duì)象。除此之外,我們還發(fā)現(xiàn)代理對(duì)象proxySubject所對(duì)應(yīng)的類繼承自java.lang.reflect.Proxy類,這也正是JDK動(dòng)態(tài)代理機(jī)制無(wú)法實(shí)現(xiàn)對(duì)class的動(dòng)態(tài)代理的原因。

15、迭代器模式

迭代器模式是與集合共生共死。一般來(lái)說(shuō),我們實(shí)現(xiàn)一個(gè)容器,就需要同時(shí)提供這個(gè)容器的迭代器,使用迭代器的好處:封裝容器內(nèi)部的實(shí)現(xiàn)細(xì)節(jié),對(duì)于不同的集合,可以提供統(tǒng)一的遍歷方式,簡(jiǎn)化客戶端的訪問(wèn)和獲取容器內(nèi)數(shù)據(jù)。

Java知識(shí)點(diǎn)梳理

 

特別需要注意的是,在迭代器模式中,具體迭代器角色和具體容器角色是耦合在一起的 —— 遍歷算法是與容器的內(nèi)部細(xì)節(jié)緊密相關(guān)的。為了使客戶程序從與具體迭代器角色耦合的困境中脫離出來(lái),避免具體迭代器角色的更換給客戶程序帶來(lái)的修改,迭代器模式抽象了具體迭代器角色,使得客戶程序更具一般性和重用性,這被稱為多態(tài)迭代。

在 Java Collection FrameWork中,提供的具體迭代器角色是定義在容器角色中的內(nèi)部類,這樣便保護(hù)了容器的封裝。但是,同時(shí)容器也提供了遍歷算法接口,并且你可以擴(kuò)展自己的迭代器。大家考慮一個(gè)問(wèn)題,為什么一定要去實(shí)現(xiàn) Iterable 這個(gè)接口呢? 為什么不直接實(shí)現(xiàn) Iterator接口呢?

看一下 JDK 中的集合類,比如 List一族或者Set一族,都是實(shí)現(xiàn)了 Iterable 接口,但并不直接實(shí)現(xiàn) Iterator 接口。仔細(xì)想一下這么做是有道理的:因?yàn)?Iterator接口的核心方法 next() 或者 hasNext() 是依賴于迭代器的當(dāng)前迭代位置的。若 Collection 直接實(shí)現(xiàn) Iterator 接口,勢(shì)必導(dǎo)致集合對(duì)象中包含當(dāng)前迭代位置的數(shù)據(jù)(指針)。當(dāng)集合在不同方法間被傳遞時(shí),由于當(dāng)前迭代位置不可預(yù)置,那么 next() 方法的結(jié)果會(huì)變成不可預(yù)知。除非再為 Iterator接口 添加一個(gè) reset() 方法,用來(lái)重置當(dāng)前迭代位置。但即使這樣,Collection 也只能同時(shí)存在一個(gè)當(dāng)前迭代位置(不能同時(shí)多次迭代同一個(gè)序列:必須要等到當(dāng)前次迭代完成并reset后,才能再一次從頭迭代)。 而選擇實(shí)現(xiàn) Iterable 接口則不然,每次調(diào)用都會(huì)返回一個(gè)從頭開始計(jì)數(shù)的迭代器(Iterator),因此,多個(gè)迭代器間是互不干擾的。

16、適配器模式

 

適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶期望的另一個(gè)接口,讓原本不兼容的接口可以合作無(wú)間。也就是說(shuō),適配器模式用于實(shí)現(xiàn)新、老接口之間的轉(zhuǎn)換與適配,其魅力在于:不改變?cè)薪涌冢瑓s還能使用新接口的功能。

Java知識(shí)點(diǎn)梳理

 

適配器模式主要包含以下四個(gè)角色,其內(nèi)涵分別為:

(1)Target: 客戶所期待的接口;

(2)Adaptee: Adapter 所包裝的對(duì)象,即被適配的類(適配者);

(3)Adapter: 一個(gè)用于包裝不兼容接口的對(duì)象的包裝類,通過(guò)包裝一個(gè)需要適配的對(duì)象,把原接口轉(zhuǎn)換成目標(biāo)接口;

(4)Client:客戶端;

適配器模式的三個(gè)特點(diǎn):

適配器對(duì)象實(shí)現(xiàn)原有接口

適配器對(duì)象組合一個(gè)實(shí)現(xiàn)新接口的對(duì)象(這個(gè)對(duì)象也可以不實(shí)現(xiàn)一個(gè)接口,只是一個(gè)單純的對(duì)象);

對(duì)適配器原有接口方法的調(diào)用被委托給新接口的實(shí)例的特定方法。

Java知識(shí)點(diǎn)梳理

 

1、模板方法模式

 

模板方法模式是一種基于繼承的代碼復(fù)用技術(shù),是一種類行為型模式,其核心在于:定義一個(gè)操作中算法的框架,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。

Java知識(shí)點(diǎn)梳理

 

18、策略模式

策略模式屬于對(duì)象的行為模式,其用意是針對(duì)一組算法,將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類中,從而使得它們可以相互替換,核心思想是:面向接口編程。

策略模式的經(jīng)典應(yīng)用包括Spring的PlatfromTransactionManager,JDK 排序策略 (不同的Comparator)等,其優(yōu)點(diǎn)包括:

(1)算法可以自由切換,避免使用多重條件判斷;

(2)擴(kuò)展性良好。

策略模式與模板方法的區(qū)別:

對(duì)于策略模式而言,一個(gè)“策略”是一個(gè)整體的(完整的)算法,算法是可以被整體替換的;而模板方法只能被替換其中的特定點(diǎn),算法流程是固定不可變的。在思想和意圖上看,模板方法更加強(qiáng)調(diào):

①定義一條線(算法流程),線上的多個(gè)點(diǎn)是可以變化的(具體實(shí)現(xiàn)在子類中完成),線上的多個(gè)點(diǎn)一定是會(huì)被執(zhí)行的,并且一定是按照特定流程被執(zhí)行的。

②算法流程是唯一的入口,對(duì)于點(diǎn)的訪問(wèn)是受限的。

19、Java 自動(dòng)裝箱、拆箱機(jī)制

Java為每種基本數(shù)據(jù)類型都提供了對(duì)應(yīng)的包裝器類型。所謂自動(dòng)裝箱機(jī)制就是自動(dòng)將基本數(shù)據(jù)類型轉(zhuǎn)換為包裝器類型,而自動(dòng)拆箱機(jī)制就是自動(dòng)將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型。在JDK中,裝箱過(guò)程是通過(guò)調(diào)用包裝器的valueOf方法實(shí)現(xiàn)的,而拆箱過(guò)程是通過(guò)調(diào)用包裝器的 xxxValue方法實(shí)現(xiàn)的(xxx代表對(duì)應(yīng)的基本數(shù)據(jù)類型)。但是,

(1)Integer、Short、Byte、Character、Long 這幾個(gè)類的valueOf方法的實(shí)現(xiàn)是類似的,共享[-128,127];

(2)Double、Float的valueOf方法的實(shí)現(xiàn)是類似的,無(wú)限不可列舉,不共享;

(3)Boolean的valueOf方法的實(shí)現(xiàn)不同于以上的整型和浮點(diǎn)型,只有兩個(gè)值,有限可列舉,共享;

什么時(shí)候裝箱/拆箱?

至于什么時(shí)候裝箱,什么時(shí)候拆箱主要取決于:在當(dāng)前場(chǎng)景下,你需要的是引用類型還是原生類型。(例如,使用equals方法時(shí)傳進(jìn)來(lái)原生類型的值);若需要的是原生類型,但傳進(jìn)來(lái)的值是引用類型,則自動(dòng)拆箱(例如,使用運(yùn)算符進(jìn)行運(yùn)算時(shí),操作數(shù)是包裝類型)。

20、內(nèi)部類

內(nèi)部類指的是在一個(gè)類的內(nèi)部所定義的類,類名不需要和源文件名相同。在Java中,內(nèi)部類是一個(gè)編譯時(shí)的概念,一旦編譯成功,內(nèi)部類和外部類就會(huì)成為兩個(gè)完全不同的類,共有四種類型:

(1)成員內(nèi)部類:成員內(nèi)部類是外圍類的一個(gè)成員,是依附于外圍類的,所以,只有先創(chuàng)建了外圍類對(duì)象才能夠創(chuàng)建內(nèi)部類對(duì)象。也正是由于這個(gè)原因,成員內(nèi)部類也不能含有 static 的變量和方法;

(2)靜態(tài)內(nèi)部類:靜態(tài)內(nèi)部類,就是修飾為static的內(nèi)部類,該內(nèi)部類對(duì)象不依賴于外部類對(duì)象,就是說(shuō)我們可以直接創(chuàng)建內(nèi)部類對(duì)象,但其只可以直接訪問(wèn)外部類的所有靜態(tài)成員和靜態(tài)方法;

(3)局部?jī)?nèi)部類:局部?jī)?nèi)部類和成員內(nèi)部類一樣被編譯,只是它的作用域發(fā)生了改變,它只能在該方法和屬性中被使用,出了該方法和屬性就會(huì)失效;

(4)匿名內(nèi)部類:定義匿名內(nèi)部類的前提是,內(nèi)部類必須要繼承一個(gè)類或者實(shí)現(xiàn)接口,格式為 new 父類或者接口(){定義子類的內(nèi)容(如函數(shù)等)}。也就是說(shuō),匿名內(nèi)部類最終提供給我們的是一個(gè)匿名子類的對(duì)象。

20.1內(nèi)部類的作用

(1)間接實(shí)現(xiàn)多重繼承,例如:

Java知識(shí)點(diǎn)梳理

 

(2)內(nèi)部類還可以很好的實(shí)現(xiàn)隱藏(一般非內(nèi)部類,是不允許有private與protected權(quán)限的),但內(nèi)部類可以。

 

21、equals, hashCode, ==

(1)== 用于判斷兩個(gè)對(duì)象是否為同一個(gè)對(duì)象或者兩基本類型的值是否相等;

(2)equals 用于判斷兩個(gè)對(duì)象內(nèi)容是否相同;

(3)hashCode是一個(gè)對(duì)象的消息摘要函數(shù),一種壓縮映射,其一般與equals()方法同時(shí)重寫;若不重寫hashCode方法,默認(rèn)使用Object類的hashCode方法,該方法是一個(gè)本地方法,由 Object 類定義的 hashCode 方法會(huì)針對(duì)不同的對(duì)象返回不同的整數(shù)。

21.1 equals與hashCode的區(qū)別

(1)一般來(lái)講,equals 這個(gè)方法是給用戶調(diào)用的,而 hashcode 方法一般用戶不會(huì)去調(diào)用;

(2)當(dāng)一個(gè)對(duì)象類型作為集合對(duì)象的元素時(shí),那么這個(gè)對(duì)象應(yīng)該擁有自己的equals()和hashCode()設(shè)計(jì),而且要遵守前面所說(shuō)的幾個(gè)原則。

21.2 在HashMap中使用可變對(duì)象作為Key帶來(lái)的問(wèn)題

 

HashMap用Key的哈希值來(lái)存儲(chǔ)和查找鍵值對(duì),如果HashMap Key的哈希值在存儲(chǔ)鍵值對(duì)后發(fā)生改變,那么Map可能再也查找不到這個(gè)Entry了。也就是說(shuō),在HashMap中可變對(duì)象作為Key會(huì)造成數(shù)據(jù)丟失。因此,

(1)在HashMap中盡量使用不可變對(duì)象作為Key,比如,使用String、Integer等不可變類型用作Key是非常明智的或者使用自己定義的不可變類。

(2)如果可變對(duì)象在HashMap中被用作鍵,那就要小心在改變對(duì)象狀態(tài)的時(shí)候,不要改變它的哈希值了,例如,可以只根據(jù)對(duì)象的標(biāo)識(shí)屬性生成HashCode。

Java知識(shí)點(diǎn)梳理

 

21.3 重新equals但不重寫HashCode會(huì)出現(xiàn)的問(wèn)題

在使用Set時(shí),若向其加入兩個(gè)相同(equals返回為true)的對(duì)象,由于hashCode函數(shù)沒有進(jìn)行重寫,那么這兩個(gè)對(duì)象的hashCode值必然不同,它們很有可能被分散到不同的桶中,容易造成重復(fù)對(duì)象

的存在。

22、什么是不可變對(duì)象

一個(gè)不可變對(duì)象應(yīng)該滿足以下幾個(gè)條件:

(1)基本類型變量的值不可變;

(2)引用類型變量不能指向其他對(duì)象;

(3)引用類型所指向的對(duì)象的狀態(tài)不可變;

(4)除了構(gòu)造函數(shù)之外,不應(yīng)該有其它任何函數(shù)(至少是任何public函數(shù))修改任何成員變量;

(5)任何使成員變量獲得新值的函數(shù)都應(yīng)該將新的值保存在新的對(duì)象中,而保持原來(lái)的對(duì)象不被修改。

23、Java的序列化/反序列化機(jī)制

使用Serializable序列化/反序列化。將實(shí)現(xiàn)了Serializable接口的對(duì)象轉(zhuǎn)換成一個(gè)字節(jié)序列,并能夠在以后將這個(gè)字節(jié)序列完全恢復(fù)為原來(lái)的對(duì)象,序列化可以彌補(bǔ)不同操作系統(tǒng)之間的差異。其中,需要注意以下幾點(diǎn):

(1)需要序列化的對(duì)象必須實(shí)現(xiàn)Serializable接口;

(2)只有非靜態(tài)字段和非transient字段進(jìn)行序列化,與字段的可見性無(wú)關(guān);

(3)序列化/反序列化的實(shí)質(zhì)上操縱的是一個(gè)對(duì)象圖;

Java知識(shí)點(diǎn)梳理

 

 此外,Java中常用到的序列化方法還有 XML、JSON 等,此不贅述。

24、Path及ClassPath環(huán)境變量

(1)Path系統(tǒng)用來(lái)指定可執(zhí)行文件的完整路徑。當(dāng)在CMD中執(zhí)行命令時(shí),如果執(zhí)行的可執(zhí)行文件不在當(dāng)前目錄下,那么系統(tǒng)就會(huì)依次搜索PATH中設(shè)置的路徑。如果在PATH中設(shè)置了JDK的安裝目錄(如在PATH中添加如下的路徑——D:ProgramFilesJavajdk1.8.0bin;D:ProgramFilesJavajdk1.8.0jrebin;),那么就可以在CMD中直接使用java、javac等命令,而不必在CMD中切換到JDK的安裝目錄下運(yùn)行該命令。

(2)ClassPath是指定程序中所使用的類文件所在的位置。ClassPath環(huán)境變量中點(diǎn)(“.”)的含義是:在當(dāng)前路徑下搜索Java類。如果編譯器按照CLASSPATH指定的路徑找不到所需要的類,則會(huì)提示“*類找不到”這樣的錯(cuò)誤。

分享到:
標(biāo)簽:知識(shí)點(diǎn) Java
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定