第一篇:13_2 第十三天 魔樂java基礎(chǔ)視頻學(xué)習(xí)筆記
1、課程名稱:DAO設(shè)計模式
2、知識點(diǎn):
2.1、上次課程的主要知識點(diǎn)
1、面向?qū)ο螅?/p>
2、Java類集;
3、JDBC使用PreparedStatement進(jìn)行數(shù)據(jù)的CRUD。
2.2、本次預(yù)計講解的知識點(diǎn)
1、熟悉程序分層的概念,以及業(yè)務(wù)層和數(shù)據(jù)層的劃分;
2、使用DAO設(shè)計模式實(shí)現(xiàn)單表映射以及泛型應(yīng)用;
3、使用DAO設(shè)計模式實(shí)現(xiàn)數(shù)據(jù)表的關(guān)系映射(一對多)。
3、具體內(nèi)容
之前的所有內(nèi)容都在本處進(jìn)行總結(jié),而且對于之前的一些概念不清楚的東西(代碼會寫)那么都可以不用去看了,把本次程序弄會了,一切就都會了,后面也就都會了。
3.1、程序分層(理解)
在一個完整的項(xiàng)目之中,對程序進(jìn)行合理的分層,可以讓開發(fā)變得更加的方便,也更加的具備層次感,每一層有每一層的開發(fā)人員,例如:可以簡單的理解為美工 + 程序相分離。
如果按照含金量來講,首先把握住業(yè)務(wù)層是整個程序的實(shí)現(xiàn)關(guān)鍵,但是對于前臺顯示更加的重要。今在項(xiàng)目之中后臺的簡歷直接有著重要的地位,但是不同層之間最為重要的連接組成部分就是接口,所天的主要任務(wù)是觀察業(yè)務(wù)層和數(shù)據(jù)層的開發(fā),而到了Java WEB 之后,才開始實(shí)現(xiàn)顯示層和控制層的開發(fā)。以整個代碼開發(fā)之中,對于后臺代碼就一定要有兩個組成接口(業(yè)務(wù)層接口,給以后的控制層使用、數(shù)據(jù)層接口,給以后的業(yè)務(wù)層使用)。·數(shù)據(jù)層(數(shù)據(jù)訪問層,Data Access Object):指的是執(zhí)行數(shù)據(jù)的具體操作,而現(xiàn)在的開發(fā)之中,大多數(shù)都是針對于數(shù)據(jù)庫的開發(fā),所以在數(shù)據(jù)層之中的主要任務(wù)是負(fù)責(zé)完成數(shù)據(jù)的CRUD,而在java之中,如果要想進(jìn)行數(shù)據(jù)的CRUD實(shí)現(xiàn),肯定使用java.sql.PreparedStatement接口;
·業(yè)務(wù)層(業(yè)務(wù)對象,Business Object,BO,又或者將其稱為Service,服務(wù)器),服務(wù)器的主要目的是清楚了基本概念之后,那么新的問題就該出現(xiàn)了,如何去區(qū)分業(yè)務(wù)層或者是數(shù)據(jù)層?下面以玉市先生根據(jù)業(yè)務(wù)需求進(jìn)行數(shù)據(jù)層的操作。一個業(yè)務(wù)層要包含多個數(shù)據(jù)層的操作。吃飯為例,說明一下。
如果說現(xiàn)在某一個項(xiàng)目業(yè)務(wù)非常復(fù)雜,可能分為若干個子業(yè)務(wù),那么久還需要一個總的業(yè)務(wù)層操作。3.2、實(shí)例分析(重點(diǎn))
下面以emp數(shù)據(jù)表(empno、ename、job、hiredate、sal、comm,都是基本字段)為例分析一個操·【業(yè)務(wù)層】增加一個新雇員信息;
|-[數(shù)據(jù)層] :要根據(jù)增加的雇員編號查看此雇員是否存在; |-[數(shù)據(jù)層]:如果雇員不存在則執(zhí)行插入操作,如果存在則不插入; |-[數(shù)據(jù)層]:直接傳入新的數(shù)據(jù)即可,如果沒有修改返回的更新行數(shù)是0; |-[數(shù)據(jù)層]:直接傳入要刪除的雇員編號即可,如果沒有此雇員信息返回的是0; |-[數(shù)據(jù)層]:返回一個雇員的完整信息; 作,客戶要求可以實(shí)現(xiàn)如下的幾個功能:
·【業(yè)務(wù)層】修改一個雇員的信息; ·【業(yè)務(wù)層】刪除一個雇員的信息;
·【業(yè)務(wù)層】根據(jù)編號查詢一個雇員的信息;
·【業(yè)務(wù)層】取得全部雇員的信息,要求可以實(shí)現(xiàn)模糊查詢和分頁顯示,查詢結(jié)果除了返回數(shù)據(jù)之外,|-[數(shù)據(jù)層]:模糊或查詢?nèi)繚M足條件的雇員數(shù)據(jù),多個數(shù)據(jù); |-[數(shù)據(jù)層]:使用COUNT()進(jìn)行滿足條件的數(shù)據(jù)統(tǒng)計。還要求知道模糊或全部查詢或全部查詢是所返回的全部數(shù)據(jù)量。
3.3、準(zhǔn)備階段(重點(diǎn))
3.3.1、VO類:負(fù)責(zé)數(shù)據(jù)的傳輸與包裝
但是現(xiàn)在有一個最為嚴(yán)重的問題出現(xiàn)了,不同層之間(這些層除了數(shù)據(jù)層要操作SQL之外,那么其它層操作的數(shù)據(jù)都應(yīng)該是對象),所以應(yīng)該有一個負(fù)責(zé)傳輸?shù)臄?shù)據(jù)對象,這個對象可以稱為Value Object(VO、POJO、TO、PO)。
但是,現(xiàn)在對于簡單Java類的開發(fā)原則也發(fā)生了一些變化:
·類名稱要和表名稱保持一致;
·為了日后類的操作方便,所有的簡單Java類必須實(shí)現(xiàn)java.io.Serializable接口; ·類中不運(yùn)行出現(xiàn)任何的基本數(shù)據(jù)類型,只能使用包裝類; ·類之中的所有屬性都必須封裝,必須都編寫setter、getter; ·類之中一定要提供無參構(gòu)造方法。
在DAO的開發(fā)之中,所有的名稱都有嚴(yán)格規(guī)定,假設(shè)現(xiàn)在的項(xiàng)目的總包名稱為:cn.mldn.oracle,那么現(xiàn)在這個VO類的保存包名稱就應(yīng)該是cn.mldn.oracle.vo。范例:定義cn.mldn.oracle.vo.Emp類
3.3.2、DatabaseConnection類:負(fù)責(zé)數(shù)據(jù)庫連接
既然現(xiàn)在要完成數(shù)據(jù)層的開發(fā),那么久一定需要數(shù)據(jù)庫的連接與關(guān)閉操作,可是如果將數(shù)據(jù)庫的連接和關(guān)閉都寫在每一個數(shù)據(jù)層之中,這樣代碼過于重復(fù),而且也不方便維護(hù),那么為了方便起見,現(xiàn)在定義一個DatabaseConnection的類,這個類專門負(fù)責(zé)取得和關(guān)閉數(shù)據(jù)庫連接。而這個類定義在cn.mldn.oracle.dbc包之中。范例:定義cn.mldn.oracle.dbc.DatabaseConnection
如果再實(shí)際的工作之中,按照DAO最早提出的標(biāo)準(zhǔn),對于數(shù)據(jù)層的實(shí)現(xiàn)類還需要實(shí)現(xiàn)數(shù)據(jù)庫的移植操作。即:對于數(shù)據(jù)庫連接類應(yīng)該變?yōu)橐粋€專門負(fù)責(zé)連接的接口,就好像以下的形式一樣:
而后如果一個項(xiàng)目可能在Oracle或DB2下運(yùn)行,那么針對于這兩種數(shù)據(jù)庫分別定義一個接口實(shí)現(xiàn)類,以對應(yīng)兩個不同的數(shù)據(jù)庫連接,但是這種開發(fā)已經(jīng)和現(xiàn)在的模式有些出入了,而且特別的麻煩,所以在本次為了和日后的開發(fā)可以更好的聯(lián)系在一起,只是定義了一個類而已。
3.4、開發(fā)數(shù)據(jù)層(重點(diǎn))
3.4.1、定義IEmpDAO接口:數(shù)據(jù)層開發(fā)標(biāo)準(zhǔn)
不同層之間的操作依靠的是接口,所以數(shù)據(jù)層的開發(fā)首先要定義出來的就是標(biāo)準(zhǔn),那么既然是標(biāo)準(zhǔn)就需要定義的是一個接口,現(xiàn)在很明顯針對的是emp表,所以這個接口的名稱就應(yīng)該為“表名稱DAO”,即:EmpDAO,但是這里有一個問題了,接口和類的命名要求是一致的,所以為了從名稱上區(qū)分出接口或者是類,則建議在接口名稱前增加一個字母“I”,表示Interface的含義,即emp這張實(shí)體表的操作標(biāo)準(zhǔn)的接口名稱為IEmpDAO,而且這個接口應(yīng)該保存在cn.mldn.oracle.dao包之中。
那么對于這個接口的開發(fā)主要是針對于數(shù)據(jù)的兩種操作(更新、查詢),所以從開發(fā)標(biāo)準(zhǔn)上對于命名
·更新操作:以“doXxx()”的方式命名,例如:doCreate()、doUpdate()、doRemove(); ·查詢操作,因?yàn)椴樵儾僮鞣譃閮深悾?/p>
|-數(shù)據(jù)查詢:以“findXxx()”或“findByXxx()”為主,例如:findAll()、findByld()、findByJob(); |-統(tǒng)計查詢:以“getXxx()”或“getByXxx()”為主,例如:getAllCount()、getByJobCount()。也有著嚴(yán)格的要求,而且必須遵守?;緲?biāo)準(zhǔn)如下:
范例:編寫IEmpDAO接口的操作標(biāo)準(zhǔn)
現(xiàn)在開發(fā)的標(biāo)準(zhǔn)只是滿足于程序需求的提出需要。
3.4.2、定義IEmpDAO接口的實(shí)現(xiàn)類
既然在接口中已經(jīng)定義了數(shù)據(jù)層的操作標(biāo)準(zhǔn),那么對于實(shí)現(xiàn)類只需要遵循數(shù)據(jù)層的CRUD操作即可,但是對于DAO接口的實(shí)現(xiàn)類需要有明確的定義,要求將其定義在:cn.mldn.oracle.dao.impl包之中; 范例:定義EmpDAOImpl子類 ·現(xiàn)在有如下一種的子類實(shí)現(xiàn)接口方式:
如果真的按照這種方式實(shí)現(xiàn)的程序,有兩個重要問題:
·對于數(shù)據(jù)層之中給出的若干方法,由服務(wù)層調(diào)用,一個服務(wù)層要執(zhí)行N個數(shù)據(jù)層,那么每次·按照異常的處理機(jī)制,如果現(xiàn)在執(zhí)行的過程之中出現(xiàn)了錯誤,那么順著throws就結(jié)束調(diào)用了,執(zhí)行的時候開一次關(guān)閉一次數(shù)據(jù)庫? 數(shù)據(jù)庫就再也無法關(guān)閉了。
按照之前的分析,一個業(yè)務(wù)要進(jìn)行多個數(shù)據(jù)層操作,所以數(shù)據(jù)庫連接與關(guān)閉交給業(yè)務(wù)層做最合適,而數(shù)據(jù)層只需要有一個Connection對象就可以操作了,它不需要關(guān)系這個對象是從哪里來的,怎么來的,只關(guān)心能不能使用。
3.4.3、定義DAO工廠類
由于不同層之間只能依靠接口取得對象,所以就一定需要定義工廠操作類,工廠類定義在cn.mldn.oracle.factory包之中,名稱為DAOFactory。范例:定義工廠類
3.5、開發(fā)業(yè)務(wù)層(重點(diǎn))3.5.1、開發(fā)業(yè)務(wù)層標(biāo)準(zhǔn)
業(yè)務(wù)層以后也是需要留給其它層進(jìn)行調(diào)用的,所以業(yè)務(wù)層定義的時候也需要首先定義出操作標(biāo)準(zhǔn),而這個標(biāo)準(zhǔn)也依然使用接口完成,對于業(yè)務(wù)層,接口命名要求:表名稱 + Service,例如:IEmpService,表示操作Emp表的業(yè)務(wù)。
范例:在cn.mldn.oracle.service包中定義IEmpService
3.5.2、定義業(yè)務(wù)層標(biāo)準(zhǔn)的實(shí)現(xiàn)類
如果現(xiàn)在要想實(shí)現(xiàn)業(yè)務(wù)層的標(biāo)準(zhǔn),必須有一個原則先把握住:一個業(yè)務(wù)層的方法操作要調(diào)用多個數(shù)據(jù)層,同時每個業(yè)務(wù)要處理數(shù)據(jù)庫的打開和關(guān)閉。
范例:定義標(biāo)準(zhǔn)實(shí)現(xiàn)類——cn.mldn.oracle.service.impl.EmpServiceImpl
3.5.3、定義Service工廠類
如果要取得IEmpService接口對象,一定也需要使用工廠類,避免耦合問題。范例:定義cn.mldn.oracle.factory.ServiceFactory類
3.6、定義測試類
一切的程序完成之后,下面就需要編寫測試程序,對于測試程序現(xiàn)在有兩種方法完成:
·方式一:可以直接編寫主方法,自己根據(jù)他的返回值結(jié)果進(jìn)行判斷是否成功; ·方式二:利用JUNIT完成,這樣的做法標(biāo)準(zhǔn),而且也方便日后調(diào)試。
如果要使用JUINT則就需要建立一個個的TestCase(測試用例),而且現(xiàn)在再進(jìn)行測試的時候,應(yīng)該首先選擇的是服務(wù)層接口,因?yàn)檫x擇不是針對于接口測試,而是針對于方法測試,方法就可以不用自己去編寫了。
范例:編寫測試程序
3.7、完成dept操作
完成了Emp操作之后,下面繼續(xù)完成dept表的操作,那么對dept的操作現(xiàn)在有如下額要求:
·【業(yè)務(wù)層】增加一個新部門;
|-【數(shù)據(jù)層】判斷增加的部門編號是否存在 |-【數(shù)據(jù)層】增加部門數(shù)據(jù); |-【數(shù)據(jù)層】調(diào)用修改操作; |-【數(shù)據(jù)層】調(diào)用刪除操作;
|-【數(shù)據(jù)層】調(diào)用根據(jù)id查詢的操作; |-【數(shù)據(jù)層】查詢?nèi)?·【業(yè)務(wù)層】修改一個部門信息; ·【業(yè)務(wù)層】刪除一個部門信息;
·【業(yè)務(wù)層】根據(jù)部門編號取得一個部門的信息; ·【業(yè)務(wù)層】查詢?nèi)康牟块T信息;
1、開發(fā)DatabaseConnection.java類,已經(jīng)開發(fā)完成;
2、開發(fā)Dept的vo類:
3、開發(fā)IDeptDAO接口
這個時候所編寫的接口,第一反應(yīng)發(fā)現(xiàn)除了參數(shù)不一樣之外,和IEmpDAO一樣,而且就算現(xiàn)在有幾百張表,對于一些基本操作:插入數(shù)據(jù)、更新全部、刪除數(shù)據(jù)、根據(jù)ID查詢數(shù)據(jù)、查詢?nèi)繑?shù)據(jù)、帶分頁查詢、統(tǒng)計分頁的數(shù)據(jù)量。沒有必要重復(fù)編寫,各個表不同的只有兩塊:VO類、ID類型。所以現(xiàn)在對于接口就必須重新設(shè)計了。
范例:定義一個公共的IDAO接口
成。
而每一張數(shù)據(jù)表,除了以上的基本功能之外,還會包括一些自己的獨(dú)特功能,所以可以在子接口中完范例:定義IDeptDAO接口
4、開發(fā)DAO接口的實(shí)現(xiàn)類:
5、在DAOFactory類之中,增加新的方法,取得IDeptDAO接口實(shí)現(xiàn)類對象;
6、開發(fā)服務(wù)層接口
7、開發(fā)服務(wù)層接口實(shí)現(xiàn)類
8、在ServiceFactory接口之中增加新的方法,可以取得IDeptService接口對象;
3.8、使用mgr字段操作
在emp表中的mgr字段,表示的是每一個雇員的領(lǐng)導(dǎo),如果現(xiàn)在要想加上這種關(guān)系,需要做如下的幾步。
1、在Emp類之中表示出領(lǐng)導(dǎo)的關(guān)系,增加一個mgr屬性;
2、修改DAO實(shí)現(xiàn)類,因?yàn)楝F(xiàn)在操作數(shù)據(jù)的時候要考慮mgr字段了。
3.9、使用deptno字段操作
Emp表中的deptno字段是一個每一個雇員所屬的部門編號,所以在這之中就會發(fā)生如下的兩類關(guān)系:
·關(guān)系一:一個雇員屬于一個部門; ·關(guān)系二:一個部門有多個雇員。
范例:首先在Emp類之中增加一個Dept的操作。
2、修改EmpDAOImplements的實(shí)現(xiàn)子類上。
4、總結(jié)
1、程序的分層操作一定要掌握;
2、基本操作,要求對于單表的CRUD靈活編寫,半小時寫完一個;
3、對于表之間的關(guān)系,必須會。
第二篇:java基礎(chǔ)總結(jié)(筆記)
一、基礎(chǔ)知識:
1、JVM、JRE和JDK的區(qū)別:
JVM(Java Virtual Machine):java虛擬機(jī),用于保證java的跨平臺的特性。
java語言是跨平臺,jvm不是跨平臺的。
JRE(Java Runtime Environment):java的運(yùn)行環(huán)境,包括jvm+java的核心類庫。
JDK(Java Development Kit):java的開發(fā)工具,包括jre+開發(fā)工具
2、環(huán)境變量path和classpath的作用是什么?
(1)path是配置Windows可執(zhí)行文件的搜索路徑,即擴(kuò)展名為.exe的程序文件所在的目錄,用于指定DOS窗口命令的路徑。
(2)Classpath是配置class文件所在的目錄,用于指定類搜索路徑,JVM就是通過它來尋找該類的class類文件的。
3、變量有什么用?為什么要定義變量?什么時候用?
答:變量的作用:用來存儲數(shù)據(jù)。
為什么要定義變量:用來不斷的存放同一類型的常量,并可以重復(fù)使用
4、&和&&的區(qū)別? 答:(1)&&會出現(xiàn)短路,如果可以通過第一個表達(dá)式判斷出整個表達(dá)式的結(jié)果,則不繼續(xù)后面表達(dá)式的運(yùn)算;
只能操作boolean類型數(shù)據(jù);
(2)&不會出現(xiàn)短路,將整個表達(dá)式都運(yùn)算。既可以操作boolean數(shù)據(jù)還可以操作數(shù)。
5、標(biāo)示符命名規(guī)則:
由數(shù)字(0-9),大小寫英文字母,以及_和$組成。
不能以數(shù)字開頭。
不能使用關(guān)鍵字來自定義命名。
6、數(shù)據(jù)類型:
(1)基本數(shù)據(jù)類型(4類8種):
整數(shù)類型:byte、short、int、long
浮點(diǎn)數(shù)類型:float、double
字符類型:char
布爾類型:boolean(ture false)(2)引用數(shù)據(jù)類型:
類
接口
數(shù)組
7、類型轉(zhuǎn)換
精度從高到低
double float long int short(char)byte
(1)自動類型轉(zhuǎn)換
將一個低精度---?高精度
(2)強(qiáng)制類型轉(zhuǎn)換
將一個高精度---?低精度(精度會下降)
8、java語言的三種技術(shù)架構(gòu)
J2EE:企業(yè)版
是為開發(fā)企業(yè)環(huán)境下的應(yīng)用程序提供的一套解決方案。
該技術(shù)體系中包含的技術(shù)如 Servlet、Jsp等,主要針對于Web應(yīng)用程序開發(fā)。
J2SE:標(biāo)準(zhǔn)版 是為開發(fā)普通桌面和商務(wù)應(yīng)用程序提供的解決方案。
該技術(shù)體系是其他兩者的基礎(chǔ),可以完成一些桌面應(yīng)用程序的開發(fā)。
比如Java版的掃雷。
J2ME:小型版
是為開發(fā)電子消費(fèi)產(chǎn)品和嵌入式設(shè)備提供的解決方案。
該技術(shù)體系主要應(yīng)用于小型電子消費(fèi)類產(chǎn)品,如手機(jī)中的應(yīng)用程序等。
9、java的跨平臺性:
通過Java語言編寫的應(yīng)用程序在不同的系統(tǒng)平臺上都可以運(yùn)行。
跨平臺的原因:
只要在需要運(yùn)行java應(yīng)用程序的操作系統(tǒng)上,先安裝一個Java虛擬機(jī)(JVM Java Virtual Machine)即可。
由JVM來負(fù)責(zé)Java程序在該系統(tǒng)中的運(yùn)行。
10、有符號數(shù)據(jù)的表示法(次重點(diǎn))原碼,反碼(原碼取反),補(bǔ)碼(反碼+1)。
11、函數(shù)
定義:函數(shù)就是定義在類中的具有特定功能的一段獨(dú)立小程序。
特點(diǎn):
定義函數(shù)可以將功能代碼進(jìn)行封裝
便于對該功能進(jìn)行復(fù)用
函數(shù)只有被調(diào)用才會被執(zhí)行
函數(shù)的出現(xiàn)提高了代碼的復(fù)用性
對于函數(shù)沒有具體返回值的情況,返回值類型用關(guān)鍵字void表示,那么該函數(shù)中的return語句如果在最后一行可以省略不寫。
函數(shù)的應(yīng)用兩個明確:
明確要定義的功能最后的結(jié)果是什么?
明確在定義該功能的過程中,是否需要未知內(nèi)容參與運(yùn)算
12、重載:
概念:在同一個類中,允許存在一個以上的同名函數(shù),只要它們的參數(shù)個數(shù)或者參數(shù)類型不同即可。
特點(diǎn):與返回值類型無關(guān),只看參數(shù)列表(參數(shù)類型以及參數(shù)個數(shù))。好處:方便于閱讀,優(yōu)化了程序設(shè)計。
13、數(shù)組:
概念:同一種數(shù)據(jù)類型的集合。
好處:可以自動給數(shù)組中的元素從0開始編號,方便操作這些元素。
14、內(nèi)存結(jié)構(gòu):
棧內(nèi)存:用于存儲局部變量,當(dāng)數(shù)據(jù)使用完,所占空間會自動釋放。
堆內(nèi)存:數(shù)組和對象,通過new建立的實(shí)例都存放在堆內(nèi)存中。
方法區(qū):靜態(tài)成員、構(gòu)造函數(shù)、常量池、線程池
本地方法區(qū):window系統(tǒng)占用
寄存器:
二、面向?qū)ο?/p>
1、面向?qū)ο笏枷耄?1)概述:面向?qū)ο笫窍鄬τ诿嫦蜻^程而言的,面向過程強(qiáng)調(diào)的是功能,面向?qū)ο髲?qiáng)調(diào)的是將功能封裝進(jìn)對象,強(qiáng)調(diào)具備功能的對象;
(2)思想特點(diǎn):
A:是符合人們思考習(xí)慣的一種思想;
B:將復(fù)雜的事情簡單化了;
C:將程序員從執(zhí)行者變成了指揮者;
比如我要達(dá)到某種結(jié)果,我就尋找能幫我達(dá)到該結(jié)果的功能的對象,如我要洗衣服我就買洗衣機(jī),至于怎么洗我不管。
(3)特征:
封裝:隱藏對象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對外提供公共訪問方式
繼承: 多個類中存在相同屬性和行為時,將這些內(nèi)容抽取到單獨(dú)一個類中,那么多個類無需再定義
這些屬性和行為,只要繼承那個類即可。
多態(tài): 一個對象在程序不同運(yùn)行時刻代表的多種狀態(tài),父類或者接口的引用指向子類對象
2、類和對象:
類:對現(xiàn)實(shí)世界中某類事物的描述,是抽象的,概念上的定義。
對象:事物具體存在的個體。3:成員變量和局部變量的區(qū)別(重點(diǎn))(1)作用域
成員變量:針對整個類有效。
局部變量:只在某個范圍內(nèi)有效。(一般指的就是方法,語句體內(nèi))(2)存儲位置
成員變量:隨著對象的創(chuàng)建而存在,隨著對象的消失而消失,存儲在堆內(nèi)存中。
局部變量:在方法被調(diào)用,或者語句被執(zhí)行的時候存在,存儲在棧內(nèi)存中。
當(dāng)方法調(diào)用完,或者語句結(jié)束后,就自動釋放。
(3)初始值
成員變量:有默認(rèn)初始值。
局部變量:沒有默認(rèn)初始值,使用前必須賦值。
4、匿名對象
(1)匿名對象就是沒有名字的對象。是對象的一種簡寫形式。
(2)應(yīng)用場景
A:只調(diào)用一次類中的方法。
B:可以作為實(shí)際參數(shù)在方法傳遞中使用
5、封裝:
指隱藏對象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對外提供公共訪問方式;比如電腦機(jī)箱、筆記本等
好處:
將變化隔離;
方便使用;
提高復(fù)用性;
提高安全性
6、關(guān)鍵字private:封裝在代碼中的體現(xiàn)
(1)私有的意思,權(quán)限修飾符
(2)用來修飾成員變量和成員函數(shù)
(3)用private修飾的成員只在本類中有效
(4)私有是封裝的一種體現(xiàn)
7、構(gòu)造方法:
(1)特點(diǎn):
方法名與類名相同
沒有返回類型
沒有返回值
(2)作用:構(gòu)造函數(shù)是用于創(chuàng)建對象,并對其進(jìn)行初始化賦值,對象一建立就自動調(diào)用相對應(yīng)的構(gòu)造函數(shù),(3)構(gòu)造方法的注意事項(xiàng):
A:如果一個自定義類沒有構(gòu)造方法,系統(tǒng)會默認(rèn)給出一個無參構(gòu)造方法。
B:如果一個自定義類提供了構(gòu)造方法,那么,系統(tǒng)將不再給出無參構(gòu)造方法。
這個時候,你可以不使用無參構(gòu)造方法。
如果你想使用,那么,就必須手動給出無參構(gòu)造方法。
建議:一般情況下,我們的自定義類都要手動給出無參構(gòu)造方法。
(4)構(gòu)造方法和成員方法的區(qū)別
A:格式區(qū)別
構(gòu)造方法和類名相同,并且沒有返回類型,也沒有返回值。
普通成員方法可以任意起名,必須有返回類型,可以沒有返回值。
B:作用區(qū)別
構(gòu)造方法用于創(chuàng)建對象,并進(jìn)行初始化值。
普通成員方法是用于完成特定功能的。
C:調(diào)用區(qū)別
構(gòu)造方法是在創(chuàng)建對象時被調(diào)用的,一個對象建立,只調(diào)用一次相應(yīng)構(gòu)造函數(shù)
普通成員方法是由創(chuàng)建好的對象調(diào)用,可以調(diào)用多次
8、構(gòu)造代碼塊:
(1)作用:給對象進(jìn)行初始化,對象一建立就執(zhí)行,而且優(yōu)先于構(gòu)造函數(shù)執(zhí)行
(2)構(gòu)造代碼塊和構(gòu)造函數(shù)的區(qū)別:
構(gòu)造代碼塊是給所有不同對象的共性進(jìn)行統(tǒng)一初始化
構(gòu)造函數(shù)是給對應(yīng)的對象進(jìn)行初始化
9、this關(guān)鍵字
(1)this關(guān)鍵字代表本類對象的一個引用,誰調(diào)用this所在的方法,this就代表誰
(2)this的使用場景
A:用于區(qū)分同名成員變量和局部變量;
B:在定義函數(shù)時,該函數(shù)內(nèi)部要用到調(diào)用該函數(shù)的對象時,因?yàn)榇藭r對象還沒建立,故this代表此對象
B:構(gòu)造函數(shù)間調(diào)用
**這個時候,this(參數(shù))必須作為第一條語句存在。
10、Person p = new Person();在內(nèi)存中做了哪些事情。
(1)將Person.class文件加載進(jìn)內(nèi)存中。(2)如果p定義在主方法中,那么,就會在??臻g開辟一個變量空間p。
(3)在堆內(nèi)存給對象分配空間。
(4)對對象中的成員進(jìn)行默認(rèn)初始化。
(5)對對象中的成員進(jìn)行顯示初始化。
(6)調(diào)用構(gòu)造代碼塊對對象進(jìn)行初始化。(如果沒有就不執(zhí)行)(7)調(diào)用構(gòu)造方法對對象進(jìn)行初始化。對象初始化完畢。
(8)將對象的內(nèi)存地址賦值給p變量,讓p變量指向該對象。
11、static關(guān)鍵字:
(1)靜態(tài)的意思,用來修飾成員變量和成員函數(shù)
(2)靜態(tài)的特點(diǎn):
隨著類的加載而加載
優(yōu)先于對象存在 對所有對象共享
可以被類名直接調(diào)用
(3)靜態(tài)的注意事項(xiàng)
A:靜態(tài)方法只能訪問靜態(tài)成員
為什么:因?yàn)殪o態(tài)的內(nèi)容是隨著類的加載而加載,它是先進(jìn)內(nèi)存的。
B:靜態(tài)方法中不能使用this,super關(guān)鍵字
C:主方法是靜態(tài)的public static void main(String[] args)
public:公共的意思,是最大權(quán)限修飾符。
static:由于jvm調(diào)用main方法的時候,沒有創(chuàng)建對象。
只能通過類名調(diào)用。所以,main必須用static修飾。
void:由于main方法是被jvm調(diào)用,不需要返回值。用void修飾。
main:main是主要的意思,所以jvm采用了這個名字。是程序的入口。
String[]:字符串?dāng)?shù)組
args:數(shù)組名
在運(yùn)行的時候,通過java命令給args數(shù)組賦值。
格式:java MainTest hello world itcast(4)靜態(tài)變量和成員變量的區(qū)別
A:調(diào)用方式
靜態(tài)變量也稱為類變量,可以直接通過類名調(diào)用。也可以通過對象名調(diào)用。
這個變量屬于類。
成員變量也稱為實(shí)例變量,只能通過對象名調(diào)用。這個變量屬于對象。
B:存儲位置
靜態(tài)變量存儲在方法區(qū)長中的靜態(tài)區(qū)。
成員變量存儲在堆內(nèi)存。
C:生命周期
靜態(tài)變量隨著類的加載而存在,隨著類的消失而消失。生命周期長。
成員變量隨著對象的創(chuàng)建而存在,隨著對象的消失而消失。
D:與對象的相關(guān)性
靜態(tài)變量是所有對象共享的數(shù)據(jù)。
成員變量是每個對象所特有的數(shù)據(jù)。
(5)靜態(tài)的優(yōu)點(diǎn)和弊端
優(yōu)點(diǎn):
對對象的共享數(shù)據(jù)進(jìn)行單獨(dú)空間的存儲,節(jié)省內(nèi)存,沒有必要每個對象都存儲一份
可直接被類名調(diào)用
弊端:
生命周期過長,隨著類的消失而消失
訪問出現(xiàn)權(quán)限,即靜態(tài)雖好但只能訪問靜態(tài)
(6)什么使用使用靜態(tài)呢?
A:當(dāng)所有對象共享某個數(shù)據(jù)的時候,就把這個成員變量定義為靜態(tài)修飾的。
B:當(dāng)某個方法沒有訪問該類中的非靜態(tài)成員,就可以把這個方法定義為靜態(tài)修飾。
靜態(tài)的生命周期比較長,所以一般不推薦使用。
(7)靜態(tài)代碼塊
A:它只執(zhí)行一次,它比main還先執(zhí)行。
B:執(zhí)行順序
靜態(tài)代碼塊--構(gòu)造代碼塊--構(gòu)造方法
12、制作API(次重點(diǎn))API(全拼):Application Program Interface 應(yīng)用程序編程接口。
(1)類中的內(nèi)容需要用文檔注釋。
(2)使用JDKbin目錄下的javadoc工具。
格式:javadoc-d 目錄-author-version ArrayTool.java
13、單例設(shè)計模式:
(1)設(shè)計模式:
解決某類問題行之有效的方法,是一種思想,是規(guī)律的總結(jié)
(2)用來保證某個類在內(nèi)存中只有一個對象
(3)保證唯一性的思想及步驟
**為了避免其他程序建立該類對象,先禁止其他程序建立該類對象,即將構(gòu)造函數(shù)私有化
**為了其他程序訪問到該類對象,須在本類中創(chuàng)建一個該類私有對象
**為了方便其他程序訪問到該類對象,可對外提供一個公共訪問方式
比如API中的Runtime類就是單例設(shè)計模式。
(4)單例設(shè)計模式的兩種方式
A:餓漢式 當(dāng)類加載的時候,就創(chuàng)建對象。
class Student
{
private Student(){}
private static final Student s = new Student();
public static Student getInstance()
{
return s;
}
}
B:懶漢式 當(dāng)使用的使用,才去創(chuàng)建對象。
class Student
{
private Student(){}
private static final Student s = null;
public static Student getInstance()
{
if(s==null)
{
//線程1就進(jìn)來了,線程2就進(jìn)來了。
s = new Student();
}
return s;
}
} 餓漢式和懶漢式的區(qū)別:
**
餓漢式是類一加載進(jìn)內(nèi)存就創(chuàng)建好了對象;
懶漢式則是類才加載進(jìn)內(nèi)存的時候,對象還沒有存在,只有調(diào)用了getInstance()方法時,對象才開始創(chuàng)建。
**
懶漢式是延遲加載,如果多個線程同時操作懶漢式時就有可能出現(xiàn)線程安全問題,解決線程安全問題
可以加同步來解決。但是加了同步之后,每一次都要比較鎖,效率就變慢了,所以可以加雙重判斷來提高程序效率。
注:開發(fā)常用餓漢式,因?yàn)轲I漢式簡單安全。懶漢式多線程的時候容易發(fā)生問題
14、Math類的使用(重點(diǎn))(1)數(shù)學(xué)操作類:該類沒有構(gòu)造函數(shù),方法均為靜態(tài)的(2)掌握內(nèi)容
A:成員變量
**E:比任何其他值都更接近e(即自然對數(shù)的底數(shù))的double值。
**PI:比任何其他值都更接近pi(即圓的周長與直徑之比)的double值。
B:成員方法
**static double abs(double a)
返回 double 值的絕對值。返回絕對值
**static double ceil(double a)
返回最小的(最接近負(fù)無窮大)double 值,該值大于等于參數(shù),并等于某個整數(shù)。
**static double floor(double a)
返回最大的(最接近正無窮大)double 值,該值小于等于參數(shù),并等于某個整數(shù)。
**max:返回兩個值中較大的那個
**min:返回兩個值中較小的那個
**static long round(double a)返回最接近參數(shù)的 long。
static int round(float a)返回最接近參數(shù)的 int。
**static double random()
返回帶正號的 double 值,該值大于等于 0.0 且小于 1.0。
**static double pow(double a, double b)
返回第一個參數(shù)的第二個參數(shù)次冪的值。
**static double sqrt(double a)
返回正確舍入的 double 值的正平方根。
15、Random類的使用(重點(diǎn))(1)產(chǎn)生隨機(jī)數(shù)的類
(2)掌握內(nèi)容
A:構(gòu)造方法
**Random()創(chuàng)建一個新的隨機(jī)數(shù)生成器。
**Random(long seed)使用單個 long 種子創(chuàng)建一個新的隨機(jī)數(shù)生成器。
B:成員方法
**int nextInt()返回下一個偽隨機(jī)數(shù),它是此隨機(jī)數(shù)生成器的序列中均勻分布的 int 值。
**int nextInt(int n)返回一個偽隨機(jī)數(shù),它是取自此隨機(jī)數(shù)生成器序列的、在 0(包括)和指定值(不包括)之間均勻分布的 int 值。
16、Scanner類的使用
(1)可以獲取從鍵盤的輸入數(shù)據(jù)
(2)掌握內(nèi)容
構(gòu)造方法:
Scanner(InputStream source)構(gòu)造一個新的 Scanner,它生成的值是從指定的輸入流掃描的。
如:Scanner sc = new Scanner(System.in);
方法摘要
sc.nextInt();獲取整型數(shù)據(jù)
sc.nextLine();獲取字符串?dāng)?shù)據(jù)
17、繼承(重點(diǎn))(1)把很多類的相同特征和行為進(jìn)行抽取,用一個類來描述。讓多個類和這個類產(chǎn)生一個關(guān)系。
這樣的話,多個類就可以省略很多代碼。這個關(guān)系就是繼承。java中用extends關(guān)鍵字表示。
(2)繼承的體系結(jié)構(gòu)
A:多個具體的對象,不斷的向上抽取共享的內(nèi)容,最終形成了一個體系。這個體系叫做繼承體系。
B:繼承體系的學(xué)習(xí)和使用原則
**學(xué)習(xí)頂層的內(nèi)容。因?yàn)樗钦麄€體系的共性內(nèi)容。
**創(chuàng)建子類使用。也就是使用底層的具體對象。
(3)繼承的特點(diǎn):
A:java中只能單繼承,沒有多繼承。
B:java可以有多重(層)繼承。
(4)繼承的好處:
繼承的出現(xiàn)提高了代碼的復(fù)用性。
繼承的出現(xiàn)讓類與類之間產(chǎn)生了關(guān)系,提供了多態(tài)的前提。
(5)子父類中的成員關(guān)系
A:成員變量
在子類方法中使用一個變量時:
首先,在方法的局部變量中找這個變量,有則使用。
否則,在本類中找成員變量,有則使用。
否則,在父類中找成員變量,有則使用。
否則,報錯。
B:成員方法
用子類對象使用一個方法時。
首先,在子類中找這個方法,有則使用。
否則,在父類中找這個方法,有則使用。
否則,報錯。
重寫和重載的區(qū)別?
重載:在同一類中。方法名相同,參數(shù)列表不同。重載可以改變返回類型。
重寫:在不同類中(子父類中)。
方法聲明相同(返回類型,方法名,參數(shù)列表均相同)。
重寫需要注意:
**子類方法的訪問權(quán)限要大于等于父類方法的訪問權(quán)限。
**靜態(tài)只能重寫靜態(tài)。但是這種情況一般不會出現(xiàn)。
構(gòu)造方法
**子類的實(shí)例化過程
***子類創(chuàng)建對象時,會先去創(chuàng)建父類的對象。
默認(rèn)是去調(diào)用父類的無參構(gòu)造方法。
***子類構(gòu)造方法中,第一行默認(rèn)是super()
***為什么子類中第一行會默認(rèn)有super()
因?yàn)樗^承父類的成員使用,使用前這些成員必須初始化,而他們是父類的成員,所以,必須通過父類進(jìn)行初始化。
所以,會先創(chuàng)建一個父類的對象。
**當(dāng)父類沒有無參構(gòu)造方法時
必須使用this或者super調(diào)用其他的構(gòu)造方法。
(6)this和super的區(qū)別
this:代表本類對象的引用。
super:代表父類的存儲空間。
18、final關(guān)鍵字(重點(diǎn))(1)最終的意思,可以用于修飾類,方法,變量。(2)final修飾的類不能被繼承。
final修飾的方法不能被重寫。
final修飾的變量是一個常量。只能被賦值一次。
內(nèi)部類只能訪問被final修飾的局部變量。
19、抽象類(重點(diǎn))(1)多個類有相同的方法聲明,但是方法體不一樣。這個時候,我們考慮把方法聲明進(jìn)行抽取。
讓子類繼承后,自己去實(shí)現(xiàn)方法體。沒有方法體的方法,我們需要用抽象標(biāo)志下。
抽象的關(guān)鍵字是:abstract。
(2)抽象類:
該方法稱為抽象方法,包含抽象方法的類就是抽象類。
(3)抽象類的特點(diǎn):
A:抽象類和抽象方法都要用abstract進(jìn)行修飾
B:抽象類不能被實(shí)例化
C:抽象類中不一定有抽象方法,但是,有抽象方法的類一定是抽象類。
(4)抽象類中數(shù)據(jù)的特點(diǎn)
A:成員變量
抽象類中可以有變量,也可以有常量。
B:成員方法
抽象類中可以有抽象方法,也可以有非抽象方法。
C:構(gòu)造方法
抽象類是一個類,所以,它有構(gòu)造方法。
雖然本身不能實(shí)例化。但是可以給子類實(shí)例化使用。
(5)抽象類中的問題
A:抽象類中是否有構(gòu)造方法?能不能被實(shí)例化?如果不能,為什么有構(gòu)造方法?
抽象類有構(gòu)造方法。
抽象類不能被實(shí)例化。
抽象類中的構(gòu)造方法供子類實(shí)例化調(diào)用。
B:抽象關(guān)鍵字abstract不可以和哪些關(guān)鍵字共存?
**private:
私有內(nèi)容子類繼承不到,所以,不能重寫。
但是abstract修飾的方法,要求被重寫。兩者沖突。
**final
final修飾的方法不能被重寫。
而abstract修飾的方法,要求被重寫。兩者沖突。
**static
假如一個抽象方法能通過static修飾,那么這個方法,就可以直接通過類名調(diào)用。
而抽象方法是沒有方法體的,這樣的調(diào)用無意義。所以,不能用static修飾。
C:抽象類中可不可以沒有抽象方法?如果可以,這樣的類有什么用嗎?
抽象類可以沒有抽象方法。
抽象類中沒有抽象方法的作用,只是為了不讓別的類建立該抽象類對象。這個在awt中有體現(xiàn)。20、接口interface(1)當(dāng)一個類中的方法都是抽象的時候,java提供了另一種表示方式,叫接口。
用interface關(guān)鍵字表示。類與接口關(guān)系用implements表示。
(2)接口的成員特點(diǎn)
A:成員變量
是常量,默認(rèn)修飾 public static final
B:成員方法
都是抽象的,默認(rèn)修飾 public abstract
(3)關(guān)系
A:類與類的關(guān)系
是繼承關(guān)系。類與類只能單繼承,可以多重繼承。
B:類和接口的關(guān)系
是實(shí)現(xiàn)關(guān)系。類可以多實(shí)現(xiàn)接口。
類在繼承一個類的同時,可以實(shí)現(xiàn)多個接口。
C:接口和接口的關(guān)系
是繼承關(guān)系。接口可以多繼承接口。
(4)接口的特點(diǎn)
A:是對外暴露的規(guī)則
B:是功能的擴(kuò)展
C:接口的出現(xiàn)降低耦合性。
耦合(類與類之間的關(guān)系)
內(nèi)聚(類完成功能的能力)
編程規(guī)范:低耦合,高內(nèi)聚。
D:接口可以多實(shí)現(xiàn)。如:CPU和主板、筆記本的USB插口、插座
(5)接口和抽象類的區(qū)別
A:抽象類只能被單繼承
接口可以多實(shí)現(xiàn),接口的出現(xiàn)避免了多繼承的局限性。
B:抽象類中的數(shù)據(jù)特點(diǎn):
成員變量:可以是變量,也可以是常量
成員方法:可以是抽象方法,也可以是非抽象方法
構(gòu)造方法:有構(gòu)造方法
接口中的數(shù)據(jù)特點(diǎn):
成員變量:是常量。默認(rèn)修飾 public static final
成員方法:都是抽象方法。都有默認(rèn)修飾 public abstract
構(gòu)造方法:沒有構(gòu)造方法
C:抽象類中定義的是繼承體系中的共性功能。
接口中定義的是繼承體系中的擴(kuò)展功能。
D:抽象類被繼承是“is a”關(guān)系:xx是yy的一種
接口被實(shí)現(xiàn)是“l(fā)ike a”關(guān)系:xx像yy的一種
21、多態(tài):
(1)同一個對象,在程序不同時刻的多種運(yùn)行狀態(tài)。舉例:動物,狗是狗,狗是動物。水(氣態(tài),液態(tài),固態(tài))(2)多態(tài)前提
A:存在著繼承或者實(shí)現(xiàn)關(guān)系
B:有方法的重寫
C:父類(接口)引用指向子類(實(shí)現(xiàn))對象
(3)多態(tài)的好處和弊端:
好處:多態(tài)的存在提高了程序的擴(kuò)展性和后期可維護(hù)性
弊端:雖然可以預(yù)先使用,但是只能訪問父類中已有的功能,運(yùn)行的是后期子類的功能內(nèi)容。
不能預(yù)先使用子類中定義的特有功能。
(4)多態(tài)中對象調(diào)用成員的特點(diǎn)
Fu f = new Zi();
A:成員變量
編譯看左邊,運(yùn)行看左邊
B:成員方法
編譯看左邊,運(yùn)行看右邊
C:靜態(tài)方法
編譯看左邊,運(yùn)行看左邊
(5)多態(tài)的思想
指揮同一批對象做事情。舉例:帶兵打仗,下課等。
22、instanceof關(guān)鍵字
A:用于判斷某個對象是否是某種類型。
B:格式
對象名 instanceof 子類(實(shí)現(xiàn))名
23、Object類:
(1)是所有類的根類,超類。
java中提供的類以及我們自定義的類都直接或者間接的繼承自O(shè)bject類。
(2)Object類中的方法
A:void finalize()
當(dāng)垃圾回收器確定不存在對該對象的更多引用時,由對象的垃圾回收器調(diào)用此方法。
B:Class getClass()
獲取對象的字節(jié)碼文件的描述類,后面再講反射的時候還會在說這個類。
String name = s.getClass().getName();
C:int hashCode()
獲取對象的哈希值。其實(shí)就是對象的內(nèi)存地址值十進(jìn)制表示
D:String toString()
返回對象的字符串表示。
表示格式:
getClass().getName()+“@”+Integer.toHexString(hashCode());
一般我們輸出對象名的時候,其實(shí)底層調(diào)用的就是該對象的toString()方法。
這種返回沒有意義,所以,我們會重寫這個方法,顯示類的成員變量信息。
E:boolean equals(Object obj)
用于比較兩個對象的地址值是否相同。
我們獲取對象后,比較它的地址值意義不大。所以也會對這個方法進(jìn)行重寫。
重寫要完成什么功能,是根據(jù)需求定的。(3)==和equals的用法:
A:==怎么用?
**可以用于比較基本數(shù)據(jù)類型,比較的就是基本數(shù)據(jù)類型的值是否相等。
**可以用于比較引用數(shù)據(jù)類型,比較的是對象的地址值是否相等。
B:equals怎么用?
equals只能用于比較引用數(shù)據(jù)類型的。
**Object提供的equals是用于比較對象地址值是否相同。
**自定義類中,如果重寫了equals方法,那么就是按照你自己的需求來比較的。
24、package關(guān)鍵字
(1)包:其實(shí)就是文件夾。用于區(qū)分不同包下相同的類名。
(2)好處:
A:對類文件進(jìn)行分類管理。
B:給類提供了多層命名空間
aaa.Demo
bbb.Demo
C:寫在程序文件的第一行。
D:包也是一種封裝形式。
25、import關(guān)鍵字
(1)導(dǎo)入包的關(guān)鍵字
(2)格式:
import 包名;(3)注意:
A:一個程序文件中只有一個package,可以有多個import。
B:用來導(dǎo)包中的類,不導(dǎo)入包中的包。
C:通常寫import mypack.Demo,明確自己使用的類。
(4)關(guān)鍵字的順序
類,包,導(dǎo)包這些關(guān)鍵的順序。
包--> 到包--> 類
26、不同修飾符可以修飾哪些內(nèi)容
本類中 同一個包中 不同包中的子類中 不同包中
private OK
默認(rèn)
OK Ok
protected OK Ok
OK public OK Ok
OK
Ok
類 構(gòu)造方法 成員變量 成員方法
private
OK OK OK 默認(rèn)
Ok Ok Ok OK protected OK OK Ok public
Ok Ok OK OK static
OK Ok final Ok
OK OK abstract Ok
OK
一般格式:
成員變量:
權(quán)限修飾符+static/final+數(shù)據(jù)類型+成員變量名
public static final int NUM = 10;
成員方法:
權(quán)限修飾符+static/final/abstract+返回類型+方法名
27、內(nèi)部類(次重點(diǎn))(1)把一個類定義在某個類中的,這個類就被稱為內(nèi)部類,內(nèi)置類,嵌套類。
(2)訪問特點(diǎn):
A:內(nèi)部類可以直接訪問外部類中的成員,因?yàn)閮?nèi)部類持有外部類的引用,格式為:外部類名.this
B:外部類要想訪問內(nèi)部類的成員,必須創(chuàng)建對象訪問。
(3)內(nèi)部類的訪問格式:
A:當(dāng)內(nèi)部類定義在外部類的成員位置,而且非私有,則可以在其他外部類中直接建立內(nèi)部類對象
格式:外部類名.內(nèi)部類名
變量名 = new 外部類對象.內(nèi)部類對象
如:Outer.Inner in = new Outer().new Inner()
B:當(dāng)內(nèi)部類在外部類成員位置,且被static修飾時
**外部其他類可直接訪問靜態(tài)內(nèi)部類的非靜態(tài)成員
格式:new 外部類名.內(nèi)部類名().內(nèi)部類成員
如:new Outer.Inner().function();
**外部其他類可直接訪問靜態(tài)內(nèi)部類的靜態(tài)成員
格式:new 外部類名.內(nèi)部類名.內(nèi)部類成員
如:new Outer.Inner.function();(4)什么使用時候內(nèi)部類呢?
假如有A類和B類,A類想直接訪問B類的成員,B類訪問A類成員的時候,需要創(chuàng)建A類對象進(jìn)行訪問,這個時候,就可以把A類定義為B類的內(nèi)部類。
(5)內(nèi)部類的位置
A:成員位置
**可以被private修飾(Body,Heart)
**可以被static修飾。(它訪問的外部類的成員必須是靜態(tài)的)
B:局部位置
**可以直接訪問外部類中的成員,因?yàn)檫€持有外部類的持用
也可以直接訪問局部成員,但是局部成員要用final修飾。
注意:局部內(nèi)部類不能用private和static修飾
(6)通過class文件我們就可以區(qū)分是否帶有內(nèi)部類,以及內(nèi)部類的位置
Outer$Inner:成員內(nèi)部類
Outer$1Inner:局部內(nèi)部類
28、匿名內(nèi)部類(局部內(nèi)部類的簡寫)(重點(diǎn))
(1)前提:繼承一個類或者實(shí)現(xiàn)一個接口
(注意不要弄混匿名內(nèi)部類的前提和多態(tài)的前提)
(2)格式:
new 父類名或者接口名()
{
重寫父類方法或者實(shí)現(xiàn)接口中的方法。
也可以自定義其他方法。
};
(3)什么時候定義匿名內(nèi)部類?
匿名內(nèi)部類只是為了簡化書寫,匿名內(nèi)部類有局限,通常定義匿名內(nèi)部類時,該類方法不超過3個
(4)匿名內(nèi)部類的好處和弊端:
好處:簡化代碼書寫
弊端:
不能直接調(diào)用自己的特有方法
不能執(zhí)行強(qiáng)轉(zhuǎn)換動作
如果該類里面方法較多,不允許使用匿名內(nèi)部類
29、模板設(shè)計模式:
在定義功能時,功能的一部分是確定的,有一部分是不確定的,而且確定的部分在使用不確定的部分,可將不確定的部分暴露出去,由該類的子類去完成。
如:求一段程序的運(yùn)行時間例子。30、異常
(1)程序運(yùn)行過程中的不正?,F(xiàn)象就叫異常。
(2)導(dǎo)致程序運(yùn)行不正常的現(xiàn)象有很多,所以,就有很多的異常對象。
而這些異常對象存在著共性的內(nèi)容,所以,可以不斷的進(jìn)行抽取。最終形成了異常的體系結(jié)構(gòu)。
異常體系的根類是:Throwable
Throwable:
|--Error:重大的問題,我們處理不了。也不需要編寫代碼處理。比如說內(nèi)存溢出。
|--Exception:一般性的錯誤,是需要我們編寫代碼進(jìn)行處理的。
|--RuntimeException:運(yùn)行時異常,這個我們也不需要處理。
其實(shí)就是為了讓他在運(yùn)行時出問題,然后我們回來修改代碼。
(3)異常的分類
異常有兩種:
編譯時被檢測異常:
該異常在編譯時,如果沒有處理(沒有拋也沒有try),編譯失敗。
該異常被標(biāo)識,代表這可以被處理。
運(yùn)行時異常(編譯時不檢測)
在編譯時,不需要處理,編譯器不檢查。
該異常的發(fā)生,建議不處理,讓程序停止。需要對代碼進(jìn)行修正。
(4)異常體系的特點(diǎn):
異常體系中的所有類及其子類對象都具備可拋性。也就是說可以被throw和throws關(guān)鍵字所操作。
(5)main方法是如何處理異常的。
A:在main里面編寫代碼進(jìn)行處理
B:交給jvm自己進(jìn)行處理。采用的是jvm的默認(rèn)處理方式。
其實(shí)就是相當(dāng)于調(diào)用了異常對象的printStackTrace()方法。
(6)Throwable類的學(xué)習(xí)
getMessage():獲取異常信息,返回字符串。
toString():獲取異常類名和異常信息,返回字符串。
printStackTrace():獲取異常類名和異常信息,以及異常出現(xiàn)在程序中的位置。返回值void。
(7)異常的處理·
A:try...catch...finally
基本格式:
try
{
可能出現(xiàn)異常的代碼
}
catch(異常對象)
{
異常處理代碼
}
finally
{
釋放資源
}
變形格式:
try...catch
try...catch...catch...try...catch...catch...finally
**多個異常同時被捕獲的時候,記住一個原則:
先逮小的,再逮大的。
**finally:永遠(yuǎn)被執(zhí)行,除非退出jvm。System.exit(0);
面試題2個。
***:final,finally,finalize區(qū)別。
final是最終的意思。它可以用于修飾類,成員變量,成員方法。
它修飾的類不能被繼承,它修飾的變量時常量,它修飾的方法不能被重寫。
finally:是異常處理里面的關(guān)鍵字。
它其中的代碼永遠(yuǎn)被執(zhí)行。特殊情況:在執(zhí)行它之前jvm退出。System.exit(0);
finalize:是Object類中的一個方法。
它是于垃圾回收器調(diào)用的方式。
***:假如catch中有return語句,finally里中的代碼會執(zhí)行嗎?
是在return前,還是在return后呢?
會,在return前執(zhí)行finally里面的代碼。
(8)Exception和RuntimeException的區(qū)別
A:Exception:一般性的錯誤,是需要我們編寫代碼進(jìn)行處理的。
B:RuntimeException:運(yùn)行時異常,這個我們也不需要處理。
其實(shí)就是為了讓他在運(yùn)行時出問題,然后我們回來修改代碼。
在用throws拋出一個的時候,如果這個異常是屬于RuntimeException的體系的時候,我們在調(diào)用的地方可以不用處理。(RuntimeException和RuntimeException的子類)
在用throws拋出一個的時候,如果這個異常是屬于Exception的體系的時候,我們在調(diào)用的地方必須進(jìn)行處理或者繼續(xù)拋出。
(9)自定義異常
定義類繼承Exception或者RuntimeException
1,為了讓該自定義類具備可拋性。
2,讓該類具備操作異常的共性方法。
class MyExcepiton extends Exception
{
MyExcepiton(){}
MyExcepiton(String message)
{
super(message);
}
}
class MyException extends RuntimeException
{
MyExcepiton(){}
MyExcepiton(String message)
{
super(message);
}
}(10)throws和throw的區(qū)別
A:有throws的時候可以沒有throw。
有throw的時候,如果throw拋的異常是Exception體系,那么必須有throws在方法上聲明。
B:throws用于方法的聲明上,其后跟的是異常類名,后面可以跟多個異常類,之間用逗號隔開
throw用于方法體中,其后跟的是一個異常對象名
三、多線程:
1、進(jìn)程和線程:
進(jìn)程:正在進(jìn)行的程序。每一個進(jìn)程執(zhí)行都有一個執(zhí)行順序,該順序是一個執(zhí)行路徑,或者叫一個控制單元。
線程:進(jìn)程內(nèi)部的一條執(zhí)行路徑或者一個控制單元。
兩者的區(qū)別:
一個進(jìn)程至少有一個線程
進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而多個線程共享內(nèi)存;
2、jvm多線程的啟動是多線程嗎?
java的虛擬機(jī)jvm啟動的是單線程,就有發(fā)生內(nèi)存泄露的可能,而我們使用java程序沒出現(xiàn)這樣的問題,也就是jvm啟動至少有兩個線程,一個執(zhí)行java程序,一個執(zhí)行垃圾回收。所以是多線程。
2、多線程的優(yōu)勢:
解決了多部分同時運(yùn)行的問題,提高效率
3、線程的弊端:
線程太多會導(dǎo)致效率的降低,因?yàn)榫€程的執(zhí)行依靠的是CPU的來回切換。
4、什么叫多線程:
一個進(jìn)程中有多個線程,稱為多線程。
5、實(shí)現(xiàn)多線程的方法:
實(shí)現(xiàn)多線程可以通過繼承Thread類和實(shí)現(xiàn)Runnable接口。
(1)繼承Thread
定義一個類繼承Thread類
復(fù)寫Thread類中的public void run()方法,將線程的任務(wù)代碼封裝到run方法中
直接創(chuàng)建Thread的子類對象,創(chuàng)建線程
調(diào)用start()方法,開啟線程(調(diào)用線程的任務(wù)run方法)
//另外可以通過Thread的getName()獲取線程的名稱。
(2)實(shí)現(xiàn)Runnable接口;
定義一個類,實(shí)現(xiàn)Runnable接口;
覆蓋接口的public void run()的方法,將線程的任務(wù)代碼封裝到run方法中;
創(chuàng)建Runnable接口的子類對象
將Runnabl接口的子類對象作為參數(shù)傳遞給Thread類的構(gòu)造函數(shù),創(chuàng)建Thread類對象
(原因:線程的任務(wù)都封裝在Runnable接口子類對象的run方法中。
所以要在線程對象創(chuàng)建時就必須明確要運(yùn)行的任務(wù))。
調(diào)用start()方法,啟動線程。
兩種方法區(qū)別:
(1)實(shí)現(xiàn)Runnable接口避免了單繼承的局限性
(2)繼承Thread類線程代碼存放在Thread子類的run方法中
實(shí)現(xiàn)Runnable接口線程代碼存放在接口的子類的run方法中;
在定義線程時,建議使用實(shí)現(xiàn)Runnable接口,因?yàn)閹缀跛卸嗑€程都可以使用這種方式實(shí)現(xiàn)
6、創(chuàng)建線程是為什么要復(fù)寫run方法?
Thread類用于描述線程。Thread類定義了一個功能,用于存儲線程要運(yùn)行的代碼,該存儲功能就是run方法。
7、start()和run方法有什么區(qū)別?
調(diào)用start方法方可啟動線程,而run方法只是thread的一個普通方法,調(diào)用run方法不能實(shí)現(xiàn)多線程;
Start()方法:
start方法用來啟動線程,實(shí)現(xiàn)了多線程運(yùn)行,這時無需等待run方法體代碼執(zhí)行完畢而直接繼續(xù)執(zhí)行下面的 代碼。通過調(diào)用Thread類的start()方法來啟動一個線程,這時此線程處于就緒(可運(yùn)行)狀態(tài),并沒有運(yùn)行,一旦得到cpu時間片(執(zhí)行權(quán)),就開始執(zhí)行run()方法,這里方法run()稱為線程體,它包含了要執(zhí)行的這個線程的內(nèi)容,Run方法運(yùn)行結(jié)束,此線程隨即終止。
Run()方法:
run()方法只是Thread類的一個普通方法,如果直接調(diào)用Run方法,程序中依然只有主線程這一個線程,其程序執(zhí)行路徑還是只有一條,還是要等待run方法體執(zhí)行完畢后才可繼續(xù)執(zhí)行下面的代碼,這樣就沒有達(dá)到多線程的目的。
8、線程的幾種狀態(tài):
新建:new一個Thread對象或者其子類對象就是創(chuàng)建一個線程,當(dāng)一個線程對象被創(chuàng)建,但是沒有開啟,這個時候,只是對象線程對象開辟了內(nèi)存空間和初始化數(shù)據(jù)。
就緒:新建的對象調(diào)用start方法,就開啟了線程,線程就到了就緒狀態(tài)。
在這個狀態(tài)的線程對象,具有執(zhí)行資格,沒有執(zhí)行權(quán)。
運(yùn)行:當(dāng)線程對象獲取到了CPU的資源。
在這個狀態(tài)的線程對象,既有執(zhí)行資格,也有執(zhí)行權(quán)。
凍結(jié):運(yùn)行過程中的線程由于某些原因(比如wait,sleep),釋放了執(zhí)行資格和執(zhí)行權(quán)。
當(dāng)然,他們可以回到運(yùn)行狀態(tài)。只不過,不是直接回到。
而是先回到就緒狀態(tài)。
死亡:當(dāng)線程對象調(diào)用的run方法結(jié)束,或者直接調(diào)用stop方法,就讓線程對象死亡,在內(nèi)存中變成了垃圾。
9、sleep()和wait()的區(qū)別:
(1)這兩個方法來自不同的類,sleep()來自Thread類,和wait()來自O(shè)bject類。
(2)sleep是Thread的靜態(tài)類方法,誰調(diào)用的誰去睡覺,即使在a線程里調(diào)用了b的sleep方法,實(shí)際上還是a去睡覺,要讓b線程睡覺要在b的代碼中調(diào)用sleep。而wait()是Object類的非靜態(tài)方法
(3)sleep()釋放資源不釋放鎖,而wait()釋放資源釋放鎖;
(4)使用范圍:wait,notify和notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用
10、多線程安全問題:
(1)原因:當(dāng)程序的多條語句在操作線程共享數(shù)據(jù)時(如買票例子中的票就是共享資源),由于線程的隨機(jī)性導(dǎo)致
一個線程對多條語句,執(zhí)行了一部分還沒執(zhí)行完,另一個線程搶奪到cpu執(zhí)行權(quán)參與進(jìn)來執(zhí)行,此時就導(dǎo)致共享數(shù)據(jù)發(fā)生錯誤。比如買票例子中打印重票和錯票的情況。
(2)解決方法:對多條操作共享數(shù)據(jù)的語句進(jìn)行同步,一個線程在執(zhí)行過程中其他線程不可以參與進(jìn)來
11、Java中多線程同步是什么?
同步是用來解決多線程的安全問題的,在多線程中,同步能控制對共享數(shù)據(jù)的訪問。如果沒有同步,當(dāng)一個線程在 修改一個共享數(shù)據(jù)時,而另外一個線程正在使用或者更新同一個共享數(shù)據(jù),這樣容易導(dǎo)致程序出現(xiàn)錯誤的結(jié)果。
12、什么是鎖?鎖的作用是什么? 鎖就是對象
鎖的作用是保證線程同步,解決線程安全問題。
持有鎖的線程可以在同步中執(zhí)行,沒有鎖的線程即使獲得cpu執(zhí)行權(quán),也進(jìn)不去。
13、同步的前提:(1)必須保證有兩個以上線程
(2)必須是多個線程使用同一個鎖,即多條語句在操作線程共享數(shù)據(jù)
(3)必須保證同步中只有一個線程在運(yùn)行
14、同步的好處和弊端
好處:同步解決了多線程的安全問題
弊端:多線程都需要判斷鎖,比較消耗資源
15、同步的兩種表現(xiàn)形式:
(1)同步代碼塊:
可以指定需要獲取哪個對象的同步鎖,使用synchronized的代碼塊同樣需要鎖,但他的鎖可以是任意對象
考慮到安全問題,一般還是使用同一個對象,相對來說效率較高。
注意:
**雖然同步代碼快的鎖可以使任何對象,但是在進(jìn)行多線程通信使用同步代碼快時,必須保證同步代碼快的鎖的對象和,否則會報錯。
**同步函數(shù)的鎖是this,也要保證同步函數(shù)的鎖的對象和調(diào)用wait、notify和notifyAll的對象是
同一個對象,也就是都是this鎖代表的對象。
格式:
synchronized(對象)
{
需同步的代碼;
}(2)同步函數(shù)
同步方法是指進(jìn)入該方法時需要獲取this對象的同步鎖,在方法上使用synchronized關(guān)鍵字,使用this對象作為鎖,也就是使用了當(dāng)前對象,因?yàn)殒i住了方法,所以相對于代碼塊來說效率相對較低。
注:靜態(tài)同步函數(shù)的鎖是該方法所在的類的字節(jié)碼文件對象,即類名.class文件
格式:
修飾詞 synchronized 返回值類型 函數(shù)名(參數(shù)列表)
{
需同步的代碼;
}
在jdk1.5后,用lock鎖取代了synchronized,個人理解也就是對同步代碼塊做了修改,并沒有提供對同步方法的修改,主要還是效率問題吧。
16、多線程的單例設(shè)計模式:保證某個類中內(nèi)存中只有一個對象
(1)餓漢式:
class Single
{
private Single(){}//將構(gòu)造函數(shù)私有化,不讓別的類建立該類對象
private static final Single s=new Single();//自己建立一個對象
public static Single getInstance()//提供一個公共訪問方式
{
return s;
}
}(2)懶漢式:
class Single
{
private Single(){}
private static Single s;
public static Single getInstance()
{
if(s==null)
s=new Single();
return s;
}
} 餓漢式和懶漢式的區(qū)別:
**
餓漢式是類一加載進(jìn)內(nèi)存就創(chuàng)建好了對象;
懶漢式則是類加載進(jìn)內(nèi)存的時候,對象還沒有存在,只有調(diào)用了getInstance()方法時,對象才開始創(chuàng)建。
**
懶漢式是延遲加載,如果多個線程同時操作懶漢式時就有可能出現(xiàn)線程安全問題,解決線程安全問題
可以加同步來解決。但是加了同步之后,每一次都要比較鎖,效率就變慢了,所以可以加雙重判斷來提高程序效率。
如將上述懶漢式的Instance函數(shù)改成同步:
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if(s==null)
s=new Single();
}
}
return s;
}
17、死鎖
兩個線程對兩個同步對象具有循環(huán)依賴時,就會發(fā)生死鎖。即同步嵌套同步,而鎖卻不同。
18、wait()、sleep()、notify()、notifyAll()wait():使一個線程處于等待狀態(tài),并且釋放所持有的對象的lock。
sleep():使一個正在運(yùn)行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException異常。
notify():喚醒一個處于等待狀態(tài)的線程,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程(一般是最先開始等待的線程),而且不是按優(yōu)先級。
Allnotity():喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
18、為什么wait()、notify()、notifyAll()這些用來操作線程的方法定義在Object類中?
(1)這些方法只存在于同步中;
(2)使用這些方法時必須要指定所屬的鎖,即被哪個鎖調(diào)用這些方法;
(3)而鎖可以是任意對象,所以任意對象調(diào)用的方法就定義在Object中。
19、多線程間通訊:
多線程間通訊就是多個線程在操作同一資源,但是操作的動作不同.(1)為什么要通信
多線程并發(fā)執(zhí)行的時候, 如果需要指定線程等待或者喚醒指定線程, 那么就需要通信.比如生產(chǎn)者消費(fèi)者的問題,生產(chǎn)一個消費(fèi)一個,生產(chǎn)的時候需要負(fù)責(zé)消費(fèi)的進(jìn)程等待,生產(chǎn)一個后完成后需要喚醒負(fù)責(zé)消費(fèi)的線程,同時讓自己處于等待,消費(fèi)的時候負(fù)責(zé)消費(fèi)的線程被喚醒,消費(fèi)完生產(chǎn)的產(chǎn)品后又將等待的生產(chǎn)線程喚醒,然后使自己線程處于等待。這樣來回通信,以達(dá)到生產(chǎn)一個消費(fèi)一個的目的。
(2)怎么通信
在同步代碼塊中, 使用鎖對象的wait()方法可以讓當(dāng)前線程等待, 直到有其他線程喚醒為止.使用鎖對象的notify()方法可以喚醒一個等待的線程,或者notifyAll喚醒所有等待的線程.多線程間通信用sleep很難實(shí)現(xiàn),睡眠時間很難把握。
20、Lock和Condition 實(shí)現(xiàn)提供比synchronized方法和語句可獲得的更廣泛的鎖的操作,可支持多個相關(guān)的Condition對象
Lock是個接口
鎖是控制多個線程對共享數(shù)據(jù)進(jìn)行訪問的工具。
JDK1.5中提供了多線程升級的解決方案:
將同步synchonized替換成了顯示的Lock操作,將Object中的wait、notify、notifyAll替換成了Condition對象。
該對象可以Lock鎖進(jìn)行獲取
Lock的方法摘要:
void lock()獲取鎖。
Condition newCondition()返回綁定到此 Lock 實(shí)例的新 Condition 實(shí)例。
void unlock()釋放鎖。
Condition方法摘要:
void await()造成當(dāng)前線程在接到信號或被中斷之前一直處于等待狀態(tài)。
void signal()喚醒一個等待線程。
void signalAll()喚醒所有等待線程。
21、停止線程:
stop方法已經(jīng)過時,如何停止線程?
停止線程的方法只有一種,就是run方法結(jié)束。如何讓run方法結(jié)束呢?
開啟多線程運(yùn)行,運(yùn)行代碼通常是循環(huán)體,只要控制住循環(huán),就可以讓run方法結(jié)束,也就是結(jié)束線程。
特殊情況:當(dāng)線程屬于凍結(jié)狀態(tài),就不會讀取循環(huán)控制標(biāo)記,則線程就不會結(jié)束。
為解決該特殊情況,可引入Thread類中的Interrupt方法結(jié)束線程的凍結(jié)狀態(tài);
當(dāng)沒有指定的方式讓凍結(jié)線程恢復(fù)到運(yùn)行狀態(tài)時,需要對凍結(jié)進(jìn)行清除,強(qiáng)制讓線程恢復(fù)到運(yùn)行狀態(tài)
22、interrupt: void interrupt()中斷線程:
中斷狀態(tài)將被清除,它還將收到一個 InterruptedException
22、守護(hù)線程(后臺線程)setDaemon(boolean on):將該線程標(biāo)記為守護(hù)線程或者用戶線程。
當(dāng)主線程結(jié)束,守護(hù)線程自動結(jié)束,比如圣斗士星矢里面的守護(hù)雅典娜,在多線程里面主線程就是雅典娜,守護(hù)線程就是圣斗士,主線程結(jié)束了,守護(hù)線程則自動結(jié)束。
當(dāng)正在運(yùn)行的線程都是守護(hù)線程時,java虛擬機(jī)jvm退出;所以該方法必須在啟動線程前調(diào)用;
守護(hù)線程的特點(diǎn):
守護(hù)線程開啟后和前臺線程共同搶奪cpu的執(zhí)行權(quán),開啟、運(yùn)行兩者都沒區(qū)別,但結(jié)束時有區(qū)別,當(dāng)所有前臺線程都結(jié)束后,守護(hù)線程會自動結(jié)束。
23、多線程join方法:
void join()等待該線程終止。
void join(long millis)等待該線程終止的時間最長為 millis 毫秒。
throws InterruptedException
特點(diǎn):當(dāng)A線程執(zhí)行到B線程的join方法時,A就會等待B線程都執(zhí)行完,A才會執(zhí)行
作用: join可以用來臨時加入線程執(zhí)行;
24、多線程優(yōu)先級:yield()方法
yield():暫停當(dāng)前正在執(zhí)行的線程對象,并執(zhí)行其他線程
setPriority(int newPriority):更改線程優(yōu)先級
int getPriority()返回線程的優(yōu)先級。
String toString()返回該線程的字符串表示形式,包括線程名稱、優(yōu)先級和線程組
(1)MAX_PRIORITY:最高優(yōu)先級(10級)(1)Min_PRIORITY:最低優(yōu)先級(1級)(1)Morm_PRIORITY:默認(rèn)優(yōu)先級(5級)
25、什么是ThreadLocal類,怎么使用它?
ThreadLocal類提供了線程局部(thread-local)變量。是一個線程級別的局部變量,并非“本地線程”。
ThreadLocal 為每個使用該變量的線程,提供了一個獨(dú)立的變量副本,每個線程修改副本時不影響其它線程對象的副本
下面是線程局部變量(ThreadLocal variables)的關(guān)鍵點(diǎn):
一個線程局部變量(ThreadLocal variables)為每個線程方便地提供了一個單獨(dú)的變量。
ThreadLocal 實(shí)例通常作為靜態(tài)的私有的(private static)字段出現(xiàn)在一個類中,這個類用來關(guān)聯(lián)一個線程。
當(dāng)多個線程訪問 ThreadLocal 實(shí)例時,每個線程維護(hù) ThreadLocal 提供的獨(dú)立的變量副本。
常用的使用可在 DAO 模式中見到,當(dāng) DAO 類作為一個單例類時,數(shù)據(jù)庫鏈接(connection)被每一個線程獨(dú)立的維護(hù),互不影響。(基于線程的單例)
26、什么時候拋出InvalidMonitorStateException異常?為什么?
調(diào)用 wait()/notify()/notifyAll()中的任何一個方法時,如果當(dāng)前線程沒有獲得該對象的鎖,那么就會拋出 IllegalMonitorStateException 的異常
也就是說程序在沒有執(zhí)行對象的任何同步塊或者同步方法時,仍然嘗試調(diào)用 wait()/notify()/notifyAll()時。由于該異常是 RuntimeExcpetion 的子類,所以該異常不一定要捕獲(盡管你可以捕獲只要你愿意
作為 RuntimeException,此類異常不會在 wait(),notify(),notifyAll()的方法簽名提及。
27、在靜態(tài)方法上使用同步時會發(fā)生什么事?
同步靜態(tài)方法時會獲取該類的“Class”對象,所以當(dāng)一個線程進(jìn)入同步的靜態(tài)方法中時,線程監(jiān)視器獲取類本身的對象鎖,其它線程不能進(jìn)入這個類的任何靜態(tài)同步方法。
它不像實(shí)例方法,因?yàn)槎鄠€線程可以同時訪問不同實(shí)例同步實(shí)例方法。
28、當(dāng)一個同步方法已經(jīng)執(zhí)行,線程能夠調(diào)用對象上的非同步實(shí)例方法嗎?
可以,一個非同步方法總是可以被調(diào)用而不會有任何問題。
實(shí)際上,Java 沒有為非同步方法做任何檢查,鎖對象僅僅在同步方法或者同步代碼塊中檢查。
如果一個方法沒有聲明為同步,即使你在使用共享數(shù)據(jù)Java照樣會調(diào)用,而不會做檢查是否安全,所以在這種情況下要特別小心。一個方法是否聲明為同步取決于臨界區(qū)訪問(critial section access),如果方法不訪問臨界區(qū)(共享資源或者數(shù)據(jù)結(jié)構(gòu))就沒必要聲明為同步的。
29、在一個對象上兩個線程可以調(diào)用兩個不同的同步實(shí)例方法嗎?
不能,因?yàn)橐粋€對象已經(jīng)同步了實(shí)例方法,線程獲取了對象的對象鎖。
所以只有執(zhí)行完該方法釋放對象鎖后才能執(zhí)行其它同步方法。30、什么是線程餓死,什么是活鎖?
線程餓死和活鎖雖然不像死鎖一樣是常見的問題,但是對于并發(fā)編程的設(shè)計者來說就像一次邂逅一樣。
當(dāng)所有線程阻塞,或者由于需要的資源無效而不能處理,不存在非阻塞線程使資源可用。
JavaAPI 中線程活鎖可能發(fā)生在以下情形:
當(dāng)所有線程在程序中執(zhí)行 Object.wait(0),參數(shù)為 0 的 wait 方法。
程序?qū)l(fā)生活鎖直到在相應(yīng)的對象上有線程調(diào)用 Object.notify()或者 Object.notifyAll()。
當(dāng)所有線程卡在無限循環(huán)中。
四、集合框架
1:String類:字符串(重點(diǎn))(1)多個字符組成的一個序列,叫字符串。
生活中很多數(shù)據(jù)的描述都采用的是字符串的。而且我們還會對其進(jìn)行操作。
所以,java就提供了這樣的一個類供我們使用。
(2)創(chuàng)建字符串對象
A:String():無參構(gòu)造
**舉例:
String s = new String();
s = “hello”;
sop(s);
B:String(byte[] bys):傳一個字節(jié)數(shù)組作為參數(shù) *****
**舉例
byte[] bys = {97,98,99,100,101};
String s = new String(bys);
sop(s);
C:String(byte[] bys,int index,int length):把字節(jié)數(shù)組的一部分轉(zhuǎn)換成一個字符串 *****
**舉例
byte[] bys = {97,98,99,100,101};
String s = new String(bys,1,2);
sop(s);
D:String(char[] chs):傳一個字符數(shù)組作為參數(shù) *****
**舉例
char[] chs = {'a','b','c','d','e'};
String s = new String(chs);
sop(s);
E:String(char[] chs,int index,int length):把字符數(shù)組的一部分轉(zhuǎn)換成一個字符串 *****
**舉例
char[] chs = {'a','b','c','d','e'};
String s = new String(chs,1,2);
sop(s);
F:String(String str):把一個字符串傳遞過來作為參數(shù)
char[] chs = {'a','b','c','d','e'};
String ss = new String(s);
sop(ss);
G:直接把字符串常量賦值給字符串引用對象(最常用)*****
**舉例
String s = “hello”;
sop(s);(3)面試題
A:請問String s = new String(“hello”);創(chuàng)建了幾個對象。
兩個。一個“hello”字符串對象,在方法區(qū)的常量池;一個s對象,在棧內(nèi)存。
B:請寫出下面的結(jié)果
String s1 = new String(“abc”);
Strign s2 = new String(“abc”);
String s3 = “abc”;
String s4 = “abc”;
sop(s1==s2);//false
sop(s1==s3);//false
sop(s3==s4);//true
C:字符串對象一旦被創(chuàng)建就不能被改變。
指的是字符串常量值不改變。(4)字符串中各種功能的方法
A:判斷
**** boolean equals(Object anObject):判斷兩個字符串的內(nèi)容是否相同,復(fù)寫了Object的方法
**** boolean equalsIgnoreCase(String anotherString):判斷兩個字符串的內(nèi)容是否相同,不區(qū)分大小寫
**** boolean contains(String s):判斷一個字符串中是否包含另一個字符串
注意:判斷字符串是否包含特殊字符.直接表示為str.contains(“.”)
boolean endsWith(String suffix):測試此字符串是否以指定的后綴結(jié)束
boolean startsWith(String suffix):測試此字符串是否以指定的前綴開始
boolean isEmpty():測試字符串是否為空
B:獲取
***** int length():返回此字符串的長度
***** char charAt(int index):返回指定索引處的 char值
***** int indexOf(int ch):返回指定字符在此字符串中第一次出現(xiàn)處的索引。
int indexOf(int ch, int fromIndex):返回在此字符串中第一次出現(xiàn)指定字符處的索引,從指定的索引開始搜索。
int indexOf(String str):返回指定子字符串在此字符串中第一次出現(xiàn)處的索引。
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次
出現(xiàn)處的索引,從指定的索引開始。
*** int lastIndexOf(int ch):返回指定字符在此字符串中最后一次出現(xiàn)處的索引。
int lastIndexOf(int ch, int fromIndex)
返回指定字符在此字符串中最后一次出現(xiàn)處的索引,從指定的索引處開始進(jìn)行反向搜索。
int lastIndexOf(String str)
返回指定子字符串在此字符串中最右邊出現(xiàn)處的索引。
int lastIndexOf(String str, int fromIndex)
返回指定子字符串在此字符串中最后一次出現(xiàn)處的索引,從指定的索引開始反向搜索。
***** String substring(int beginIndex)(注意:該方法substring的String是小寫??!)
返回一個新的字符串,它是此字符串的一個子字符串。
String substring(int beginIndex, int endIndex)(注意該方法的String是小寫!!)
返回一個新字符串,它是此字符串的一個子字符串,包含頭不包含尾。
C:轉(zhuǎn)換
***** byte[] getBytes():(很常用!)從字符串到字節(jié)數(shù)組的方法
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
將字符從此字符串復(fù)制到目標(biāo)字符數(shù)組。
***** char[] toCharArray():(很常用!)從字符串到字符數(shù)組的方法
**** static String copyValueOf(char[] data)
返回指定數(shù)組中表示該字符序列的 String。
static String copyValueOf(char[] data, int offset, int count)
返回指定數(shù)組中表示該字符序列的 String。
***** static String valueOf(數(shù)據(jù)類型):把該數(shù)據(jù)類型的數(shù)據(jù)轉(zhuǎn)換成字符串。
*** String toLowerCase():把字符串轉(zhuǎn)換成小寫
String toUpperCase():把字符串轉(zhuǎn)換成大寫
*** 字符串的連接
String concat(String str):將指定字符串連接到此字符串的結(jié)尾。
D:替換
String replace(char oldChar, char newChar):用新字符替換舊字符(替換所有)
String replace(String target, String replacement):用新的子串換舊串
E:分割
String[] split(String regex):根據(jù)指定的字符串把一個字符串分割成一個字符串?dāng)?shù)組
F:
String trim():去除字符串的前后空格
G:
int compareTo(String anotherString)
按字典順序比較兩個字符串。
int compareToIgnoreCase(String str)
按字典順序比較兩個字符串,不考慮大小寫。
(5)練習(xí)
1:模擬登錄,給三次機(jī)會,并提示還有幾次.默認(rèn)的用戶名和密碼為admin。區(qū)分大小寫。
自己從鍵盤輸入用戶名和密碼。
2:給定一個字符串統(tǒng)計,統(tǒng)計大寫字母,小寫字母,數(shù)字出現(xiàn)的個數(shù).***注意:不包括特殊字符
從鍵盤輸入一個不包含特殊字符的字符串(只有26個字母和0-9組成)。
3:給定一個字符串,把它變成首字母大寫,其他字母小寫的字符串.從鍵盤輸入一個字符串,全部26個字母組成的。
4:子串在整串中出現(xiàn)的次數(shù)。
也就是說:獲取一個字符串中,指定的字串在該字符串中出現(xiàn)的次數(shù).例如:
“nbasdnbafllgnbahjnbakqqqqlnba” 在這個字符串中,多有個nba.5:對字符串中字符進(jìn)行自然順序排序。
“basckd”-->“abcdks”
先留做思考內(nèi)容:
6:兩個字符串的最大相同子串。
兩個字符串的最大相同子串。
比如:
“sadabcdfghjkl”
werabcdtyu“
2:StringBuffer(1)字符串的緩沖區(qū),是一個容器。
(2)它和String的區(qū)別
它是緩沖區(qū)可變長度的。
(3)構(gòu)造方法
StringBuffer()構(gòu)造一個其中不帶字符的字符串緩沖區(qū),初始容量為 16 個字符。
StringBuffer(int num)構(gòu)造一個不帶字符,但具有指定初始容量的字符串緩沖區(qū)。
StringBuffer(String str)構(gòu)造一個字符串緩沖區(qū),并將其內(nèi)容初始化為指定的字符串內(nèi)容。
(4)常用方法
A:增加數(shù)據(jù)
**append :添加各種類型的數(shù)據(jù)
**insert : 在容器指定位置插入各種類型的數(shù)據(jù)。
B:刪除數(shù)據(jù)
**deleteCharAt : 刪除指定位置的字符
**delete 還可以用于清空StringBuffer的緩沖區(qū)
C:替換
**replace
D:獲取
**charAt
E:長度和容量
**length()元素的個數(shù)
**capacity 元素的理論值
F:獲取元素的位置
**indexOf
**lastIndexOf
G:截取
**substring(int start)
**substring(int start,int end)
H:反轉(zhuǎn)
**reverse(5)字符串和StringBuffer的轉(zhuǎn)換
String-->StringBuffer通過構(gòu)造:
如:StringBuffer sb = new StringBuffer(String str)
StringBuffer--String通過toString方法
如:StringBuffer sb = new StringBuffer();
sb.toString();
3:StringBuilder 和StringBuffer的功能是一樣的,但是有區(qū)別:
StringBuffer(JDK1.0)是線程安全的。
StringBuilder(JDK1.5)不保證線程安全。一般來說,我們寫的程序都是單線程的,所以,用StringBuilder,效率高。
JDK版本的升級原則:
A:提高效率
B:提高安全性
C:簡化書寫
4:基本數(shù)據(jù)類型的對象包裝類
(1)為了更方便的操作每個基本數(shù)據(jù)類型,java對其提供了很多的屬性和方法供我們使用。
(2)用途:
**將基本數(shù)據(jù)類型封裝成對象的好處在于可以在對象中定義更多的功能操作該數(shù)據(jù)。
**常用的操作之一:用于基本數(shù)據(jù)類型與字符串之間的轉(zhuǎn)換。
A:方便操作
B:用于和字符串進(jìn)行相互轉(zhuǎn)換
(3)基本數(shù)據(jù)類型和對象類型的對應(yīng)
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character(4)構(gòu)造方法
字段摘要:
static int MAX_VALUE 值為 2^31-1 的常量,它表示 int 類型能夠表示的最大值
static int MIN_VALUE 值為-2^31 的常量,它表示 int 類型能夠表示的最小值
static Class
Integer(int value)構(gòu)造一個新分配的Integer對象,它表示指定的int值。
Inreger(String s)注意:s必須是純數(shù)字的字符串。否則會有異常NumberFormatException
(5)幾個常用的方法
Integer.toBinaryString();
以二進(jìn)制(基數(shù) 2)無符號整數(shù)形式返回一個整數(shù)參數(shù)的字符串表示形式。
Integer.toOctalString();
以八進(jìn)制(基數(shù) 8)無符號整數(shù)形式返回一個整數(shù)參數(shù)的字符串表示形式。
Integer.toHexString();
以十六進(jìn)制(基數(shù) 16)無符號整數(shù)形式返回一個整數(shù)參數(shù)的字符串表示形式。
static int Integer.parseInt(String s)將字符串參數(shù)作為有符號的十進(jìn)制整數(shù)進(jìn)行解析,字符串必須是int型范圍內(nèi)的數(shù)字字符串
static int Integer.parseInt(String s,int basic)
使用第二個參數(shù)指定的基數(shù),將字符串參數(shù)解析為有符號的整數(shù).字符串必須是int型范圍內(nèi)的數(shù)字字符串
short shortValue()以short類型返回該Integer的值。
int intValue()以int類型返回該Integer的值。
static Integer valueOf(int num)返回一個表示指定的 int 值的 Integer 實(shí)例。
static Integer valueOf(String s)返回保存指定的String的值的Integer對象。
static Integer valueOf(String s, int radix)
返回一個Integer對象,該對象中保存了用第二個參數(shù)提供的基數(shù)進(jìn)行
解析時從指定的String中提取的值。
(6)類型轉(zhuǎn)換
int--Integer
int num = 20;
A:Integer i = new Integer(num);
B:Integer i = Integer.valueOf(num);
Integer--int
Integer i = new Integer(20);
A:int num = i.intValue();
int--String
int num = 20;
A:String s = String.valueOf(num);
B:String s = ”“+num;
C:String s = Integer.toString(num);
String--int
String s = ”20“;
A:int num = Integer.parseInt(s);
B:Integer i = new Integer(s);或者Integer i = Integer.valueOf(s);
int num = i.intValue();
6、集合框架:
(1)為什么出現(xiàn)集合類?
面向?qū)ο髮κ挛锏捏w現(xiàn)都是以對象的形式,為了方便對多個對象的操作,就對對象進(jìn)行存儲。
集合就是存儲對象最常用的一種方式.(2)數(shù)組和集合都是容器,兩者有何不同?
**數(shù)組長度固定,而集合長度是可變的**數(shù)組值可以存儲對象,還可以存儲基本數(shù)據(jù)類型;而集合只能存儲對象
**數(shù)組存儲數(shù)據(jù)類型是固定的,而集合存儲的數(shù)據(jù)類型不固定
(3)集合類的特點(diǎn):
集合只能存儲對象
集合的長度是可變的 集合可以存儲不同類型的對象
(4)集合類框架(重要?。∫智鍘追N容器間的區(qū)別):
**Collection:頂層接口
|--->List:列表,元素是有序的(元素帶角標(biāo)索引),可以有重復(fù)元素,可以有null元素。
|--->ArrayList(JDK1.2):底層的數(shù)據(jù)結(jié)構(gòu)是數(shù)組數(shù)據(jù)結(jié)構(gòu),特點(diǎn)是查詢速度快(因?yàn)閹Ы菢?biāo)),但是增刪速度稍慢,因?yàn)楫?dāng)元素多時,增刪一個元素則所有元素的角標(biāo)都得改變
線程不同步。默認(rèn)長度是10,當(dāng)超過長度時,按50%延長集合長度。
|--->LinkedList(JDK1.2):底層數(shù)據(jù)結(jié)構(gòu)式鏈表數(shù)據(jù)結(jié)構(gòu)(即后面一個元素記錄前一個),特點(diǎn):查詢速度慢,因?yàn)槊總€元素只知道前面一個元素,但增刪速度快
因?yàn)樵卦俣?,增刪一個,只要讓其前后的元素重新相連即可
線程是不同步的。
|--->Vector(JDK1.0):底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組數(shù)據(jù)結(jié)構(gòu).特點(diǎn)是查詢和增刪速度都很慢。
默認(rèn)長度是10,當(dāng)超過長度時,按100%延長集合長度。
線程同步。
(Vector功能跟ArrayList功能一模一樣,已被ArrayList替代)
**List使用注意!
|--->ArrayList:
(1)當(dāng)往ArrayList里面存入元素沒什么要求時,即只要求有序就行時;
(2)當(dāng)往ArrayList里面存入元素要求不重復(fù)時,比如存入學(xué)生對象,當(dāng)同名同姓時
視為同一個人,則不往里面存儲。則定義學(xué)生對象時,需復(fù)寫equals方法
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
return false;
Student stu =(Student)obj;
return this.name.equals(stu.name)&&this.age==stu.age;
}
則往ArrayList集合通過add存入學(xué)生對象時,集合底層自己會調(diào)用學(xué)生類的equals方法,判斷重復(fù)學(xué)生則不存入。
注:對于List集合,無論是add、contains、還是remove方法,判斷元素是否相同,都是通過復(fù)寫equals方法來判斷!
|--->LinkedList
(1)LinkLedist的特有方法:
boolean offerFirst(E e)在此列表的開頭插入指定的元素。
boolean offerLast(E e)在此列表末尾插入指定的元素。
E peekFirst()獲取但不移除此列表的第一個元素;如果此列表為空,則返回 null。
E peekLast()獲取但不移除此列表的最后一個元素;如果此列表為空,則返回 null。
E pollFirst()獲取并移除此列表的第一個元素;如果此列表為空,則返回 null。
E pollLast()獲取并移除此列表的最后一個元素;如果此列表為空,則返回 null。
(2)通過LinkLedist的特有方法,可以實(shí)現(xiàn)某些數(shù)據(jù)特殊方式的存取,比如堆棧和隊列。
一般情況下,使用哪種List接口下的實(shí)現(xiàn)類呢?
如果要求增刪快,考慮使用LinkedList
如果要求查詢快,考慮使用ArrayList
如果要求線程安全,考慮使用Vector。
|--->Set:集合,元素是無序的(因?yàn)闆]有索引),元素不可以重復(fù)??梢杂衝ull元素。
|--->HashSet(JDK1.2):底層數(shù)據(jù)結(jié)構(gòu)是哈希表、存取速度快、元素唯
一、線程不同步。
保證性元素唯一的原理:
先判斷元素的hashCode值是否相同,再判斷兩元素的equals方法是否為true
(往HashSet里面存的自定義元素要復(fù)寫hashCode和equals方法,以保證元素的唯一性!)
|--->TreeSet:底層數(shù)據(jù)結(jié)構(gòu)式二叉樹。可以對Set集合中的元素進(jìn)行排序。元素有序、線程不同步。
保證元素唯一性的依據(jù):compareTo方法return 0
TreeSet排序的第一種方式:讓元素自身具備比較性,比如八種基本數(shù)據(jù)類型或則字符串,實(shí)現(xiàn)Compareble接口,覆蓋compareTo方法,此方式是元素的自然順序
TreeSet排序的第一種方式:當(dāng)元素自身不具備比較性(比如存儲學(xué)生對象時)或者具備的比較性不是我們所需要的比較性時(比如想字符串的長度排序),此時就需要讓集合自身具備自定義的比較性。
那如何讓集合自身具備比較性呢?可在集合初始化時,就讓集合具備比較方式。即定義一個類,實(shí)現(xiàn)Comparator接口,覆蓋compare方法。
**Set集合使用注意事項(xiàng):
(1)HashSet:
通過new的方式往HashSet里面存的元素的hashCode都不同,但通常我們定義對象,比如學(xué)生對象時,雖然是new的兩個學(xué)生對象,但是當(dāng)他們name和age一樣時,我們認(rèn)為是
同一個對象,所以為了保證元素的唯一性,我們通常在往HashSet集合里面存儲元素時,在定義對象的類中通常復(fù)寫hashCode和equals方法。
public int hashCode()
{
return name.hashCode()+age*39;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
return false;
Student stu =(Student)obj;
return this.name.equals(stu.name)&&this.age==stu.age;
}
HashSet是如何保證元素唯一性的呢?
**如果兩元素的hashCode值不同,則不會調(diào)用equals方法
**如果兩元素的hashCode值相同,則繼續(xù)判斷equals是否返回true;
**hashCode和equals方法雖然定義在自定義對象類里面,但不是我們手動調(diào)用
而是往HashSet集合里面存儲元素的時候,集合底層自己調(diào)用hashCode和equals
它自己拿對象去判斷,自己判斷兩元素是否是同一個元素。
(2)TreeSet:
TreeSet要求往里面存的元素具備比較性,否則會報錯。
TreeSet排序的第一種方式:讓元素自身具備比較性
定義對象類,實(shí)現(xiàn)Compareble接口,復(fù)寫compareTo方法,此方式是元素的自然順序
class Student implements Comparable
{
private String name;
private int age;
public Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public int compareTo(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException(”不是學(xué)生對象!“);
Student stu =(Student)obj;
int num = this.age-stu.age;
if(num==0)
return this.name.compareTo(stu.name);
return num;
}
}
TreeSet排序的第一種方式:讓集合具備比較性
當(dāng)元素自身不具備比較性(比如存儲學(xué)生對象時)或者具備的 比較性不是我們所需要的比較性時(比如想字符串的長度排序),此時就需要讓集合自身具備自定義的比較性。
那如何讓集合自身具備比較性呢?可在集合初始化時,就讓集合具備比較方式。即定義一個類,實(shí)現(xiàn)Comparator接口,覆蓋compare方法。
class StringLengthComparator implements Comparator
{
public int compare(Object obj1,Object obj2)
{
String s1 =(String)obj1;
String s2 =(String)obj2;
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
}
}
class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new StringLengthComparator());
ts.add(”addfg“);
ts.add(”dfg“);
ts.add(”agtuug“);
ts.add(”vgjkg“);
sop(ts);
}
}
基本數(shù)據(jù)類型或字符串對象均實(shí)現(xiàn)了Comparable接口,故同種類型基本數(shù)據(jù)間具備比較性,即自然順序。
**Map:頂層接口,該集合存儲的是鍵值對,而且鍵是唯一的,Map和Set很像,Set集合底層就是使用了Map集合。
Map集合沒有迭代器,要取出元素必須先將Map集合轉(zhuǎn)換成Set集合才能遍歷元素
|--->HashTable(JDK1.0):
底層是哈希表數(shù)據(jù)結(jié)構(gòu);
不可以使用null鍵和null值;
用作鍵的對象必須實(shí)現(xiàn)hashCode和equals方法來保證鍵的唯一性
線程同步,效率低
|--->HashMap(JDK1.2):
底層是哈希表數(shù)據(jù)結(jié)構(gòu);
允許使用null鍵和null值;
線程不同步,效率高;
保證元素唯一性的:
原理:先判斷元素的hashCode值是否相同,再判斷兩元素的equals方法是否為true
(往HashSet里面存的自定義元素要復(fù)寫hashCode和equals方法,以保證元素的唯一性!)
class Student {
private String name;
private int age;
public Student(String name, int age){
super();
this.name = name;
this.age = age;} public int getAge(){
return age;} public void setAge(int age){
this.age = age;} public String getName(){
return name;} public void setName(String name){
this.name = name;}
@Override public int hashCode(){
return name.hashCode()+age*34;} @Override public boolean equals(Object obj){
if(!(obj instanceof Student))
return false;
Student stu =(Student)obj;
return this.name.equals(stu.name)&&this.age==stu.age;} public class HashMapDemo1 { public static void main(String[] args){
Map
hmap.put(new Student(”001“,20), ”beijing“);
hmap.put(new Student(”002“,25), ”hebei“);
hmap.put(new Student(”003“,50), ”hainan“);
hmap.put(new Student(”001“,20), ”beijing“);
System.out.println(hmap.size());
Set
Iterator
while(it.hasNext()){
Student stu = it.next();
String addr = hmap.get(stu);
System.out.println(stu.getName()+”..“+stu.getAge()+”::“+addr);
}
}
}
|--->TreeMap(JDK1.0):
底層是二叉樹結(jié)構(gòu);
允許使用null鍵和null值;
線程不同步;
可以給Map集合中的鍵進(jìn)行排序.TreeMap排序的第一種方式:讓元素自身具備比較性,比如八種基本數(shù)據(jù)類型或則字符串,實(shí)現(xiàn)Compareble接口,覆蓋compareTo方法,此方式是元素的自然順序
TreeMap排序的第一種方式:當(dāng)元素自身不具備比較性(比如存儲學(xué)生對象時)或者具備的比較性不是我們所需要的比較性時(比如想字符串的長度排序),此時就需要讓集合自身具備自定義的比較性。
那如何讓集合自身具備比較性呢?可在集合初始化時,就讓集合具備比較方式。即定義一個類,實(shí)現(xiàn)Comparator接口,覆蓋compare方法。
class Student implements Comparable
private String name;
private int age;
public Student(String name, int age){
super();
this.name = name;
this.age = age;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
@Override
public int compareTo(Student stu){
int num = new Integer(this.age).compareTo(new Integer(stu.age));
if(num==0)
return this.name.compareTo(stu.name);
return num;
}
}
public class HashMapDemo1 {
public static void main(String[] args){
Map
tmap.put(new Student(”001“,20), ”beijing“);
tmap.put(new Student(”002“,25), ”hebei“);
tmap.put(new Student(”003“,50), ”hainan“);
tmap.put(new Student(”001“,20), ”beijing“);
System.out.println(tmap.size());
Set
Iterator
while(it1.hasNext()){
Student stu = it1.next();
String addr = tmap.get(stu);
System.out.println(stu.getName()+”..“+stu.getAge()+”::“+addr);
}
}
}
**Iterator:對collection進(jìn)行迭代的迭代器.迭代器取代了Enumeration。
迭代器和枚舉的區(qū)別:
迭代器允許調(diào)用者利用定義良好的語義在迭代期間從迭代器所指向的collection移除元素
方法名稱得到了改進(jìn),簡化書寫
**LisIterator:系列表迭代器,允許程序員按任一方向遍歷列表、迭代期間修改列表
**Comparable:此接口強(qiáng)行對實(shí)現(xiàn)它的每個類的對象進(jìn)行整體自然排序。使元素具備比較性
**Comparator:強(qiáng)行對某個對象collection進(jìn)行整體排序的比較函數(shù),使集合具備比較性
**Collections:此類完全由在 collection 上進(jìn)行操作或返回 collection 的靜態(tài)方法組成。
**Arrays:此類包含用來操作數(shù)組(比如排序和搜索)的各種靜態(tài)方法
7、集合類各容器方法:
**接口Collection方法摘要(沒有構(gòu)造方法)
a)添加:
i.boolean add(E e)
j.boolean addAll(Collection c)b)刪除:
i.void clear():清空容器
j.boolean remove(Objec object):
k.boolean removeAll(Collection c): c)判斷:
i.boolean contains(Object object):判斷是否包含此元素
j.boolean containsAll(Collection c):判斷是否包含一堆元素
k.boolean equals(Object object):比較此collection與指定對象是否相等
m.boolean isEmpty():判斷是否集合為空
d)獲?。?/p>
h.Iterator iterator():取出
i.int hashCode():返回此collection的哈希值
j.int size():返回此collection中元素的個數(shù)
k.boolean retainAll(Collection c):取交集
m.Object toArray():返回此collection中所有元素的數(shù)組
n.T[] toArray(T[] a):返回包含此collection中所有元素的數(shù)值。*****List集合子類及其方法
(1)List接口是Collection接口的一個子接口。
(2)List接口中的元素有如下特點(diǎn)(對角標(biāo)的操作都是特有方法,因?yàn)橛行?:
A:元素有序(存儲順序和取出順序一致)
B:元素可以重復(fù)
(3)List接口中的特有方法
A:add(int index,Object obj):在指定位置加入元素
B:remove(int index):移除指定位置的元素
C:set(int index,Object obj):修改指定位置的元素
D:get(int index):獲取指定位置的元素
E:indexOf(Object obj):獲取指定元素的位置
F:subList(int start,int end):從一個大的List中截取一個小的List
G:listIterator():返回一個List接口特有的迭代器(1)、ArrayList:
|--->構(gòu)造方法摘要:(少用,不是重點(diǎn))ArrayList():構(gòu)造一個初始容量為 10 的空列表。
ArrayList(Collection extends E> c): 構(gòu)造一個包含指定 collection 的元素的列表,ArrayList(int initialCapacity): 構(gòu)造一個具有指定初始容量的空列表。
|--->方法摘要:
|--->添加:
boolean add(E e): 將指定的元素添加到此列表的尾部。
void add(int index, E element): 將指定的元素插入此列表中的指定位置。
boolean addAll(Collection extends E> c):按照指定 collection 的迭代器所返回的元素順序,將該 collection 中的所有元素添加到此列表的尾部
boolean addAll(int index, Collection extends E> c): 從指定的位置開始,將指定 collection
中的所有元素插入到此列表中。|--->刪除:
void clear(): 移除此列表中的所有元素。
E remove(int index): 移除此列表中指定位置上的元素。
boolean remove(Object o): 移除此列表中首次出現(xiàn)的指定元素(如果存在)。
protected void removeRange(int fromIndex, int toIndex):
移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之間的所有元素。
boolean removeAll(Collection> c): 從列表中移除指定 collection 中包含的其所有元素
|--->獲取:
E get(int index): 返回此列表中指定位置上的元素。
int indexOf(Object o): 返回此列表中首次出現(xiàn)的指定元素的索引,或如果此列表不包含元素,則返回-1。
int lastIndexOf(Object o)返回此列表中最后一次出現(xiàn)的指定元素的索引,或如果此列表不包含索引,則返回-1。
public List
和 toIndex(不包括)之間的部分視圖。
Iterator
ListIterator
|--->修改:(特有方法!)
E set(int index, E element): 用指定的元素替代此列表中指定位置上的元素。
(2)LinkedList: |--->構(gòu)造方法摘要:
LinkedList(): 構(gòu)造一個空列表。
LinkedList(Collection extends E> c): 構(gòu)造一個包含指定 collection 中的元素的列表,這些元素按其 collection 的迭代器返回的順序排列。
|--->方法摘要:(特有的)
|--->添加
void addFirst(E e): 將指定元素插入此列表的開頭。
void addLast(E e): 將指定元素添加到此列表的結(jié)尾。
|--->獲取元素,但不刪除元素
E get(int index): 返回此列表中指定位置處的元素。
E getFirst(): 返回此列表的第一個元素。
E getLast(): 返回此列表的最后一個元素。
|--->獲取元素且刪除元素
E remove(): 獲取并移除此列表的頭(第一個元素)。
E remove(int index): 移除此列表中指定位置處的元素。
boolean remove(Object o): 從此列表中移除首次出現(xiàn)的指定元素(如果存在)。
E removeFirst(): 移除并返回此列表的第一個元素。
E removeLast(): 移除并返回此列表的最后一個元素。
|--->修改
E set(int index, E element)將此列表中指定位置的元素替換為指定的元素。
(3)Vector |--->構(gòu)造方法摘要:
Vector(): 構(gòu)造一個空向量,使其內(nèi)部數(shù)據(jù)數(shù)組的大小為 10,其標(biāo)準(zhǔn)容量增量為零。
Vector(Collection extends E> c): 構(gòu)造一個包含指定 collection 中的元素的向量,這些元素按其 collection 的迭代器返回元素的順序排列。
|--->方法摘要:
|--->添加:
boolean add(E e): 將指定元素添加到此向量的末尾。
void add(int index, E element): 在此向量的指定位置插入指定的元素。
boolean addAll(Collection extends E> c):
將指定 Collection 中的所有元素添加到此向量的末尾,按照指定 collection 的迭代器所返回的順序添加這些元素。
boolean addAll(int index, Collection extends E> c): 在指定位置將指定 Collection 中的所有元素插入到此向量中。
|--->獲取:
Enumeration
Vector特有的取出方式:
枚舉和迭代器很像,其實(shí)枚舉和迭代器是一樣的,只是因?yàn)槊杜e的名稱和方法的名稱
名字都過長,所以枚舉被迭代器取代了。
|--->枚舉Enumeration的方法摘要:
boolean hasMoreElements(): 測試此枚舉是否包含更多的元素。
E nextElement(): 如果此枚舉對象至少還有一個可提供的元素,則返回此枚舉的下一個元素。
*****Set集合子類及其方法
(1)HashSet:它不保證set的迭代順序;特別是它不保證該順序恒久不變.此類允許使用null元素。
|--->構(gòu)造方法:
HashSet()構(gòu)造一個新的空 set,其底層 HashMap 實(shí)例的默認(rèn)初始容量是 16,加載因子是 0.75。
HashSet(Collection extends E> c)構(gòu)造一個包含指定 collection 中的元素的新 set。
|--->方法摘要:
boolean add(E e)如果此 set 中尚未包含指定元素,則添加指定元素。
void clear()從此 set 中移除所有元素。
Object clone()返回此 HashSet 實(shí)例的淺表副本:并沒有復(fù)制這些元素本身。
boolean contains(Object o)如果此 set 包含指定元素,則返回 true。
boolean isEmpty()如果此 set 不包含任何元素,則返回 true。
Iterator
boolean remove(Object o)如果指定元素存在于此 set 中,則將其移除。
int size()返回此 set 中的元素的數(shù)量(set 的容量)。
(2)TreeSet:使用元素的自然順序?qū)υ剡M(jìn)行排序,或者根據(jù)創(chuàng)建 set 時提供的 Comparator 進(jìn)行排序.|--->構(gòu)造方法:
TreeSet()構(gòu)造一個新的空 set,該set根據(jù)其元素的自然順序進(jìn)行排序。
TreeSet(Collection extends E> c)
構(gòu)造一個包含指定 collection 元素的新 TreeSet,它按照其元素的自然順序進(jìn)行排序。
TreeSet(Comparator super E> comparator)構(gòu)造一個新的空 TreeSet,它根據(jù)指定比較器進(jìn)行排序。
|--->方法摘要:
添加:
boolean add(E e)將指定的元素添加到此 set(如果該元素尚未存在于 set 中)。
boolean addAll(Collection extends E> c)將指定 collection 中的所有元素添加到此 set 中。
刪除:
void clear()移除此 set 中的所有元素。
boolean remove(Object o)將指定的元素從 set 中移除(如果該元素存在于此 set 中)。
E pollFirst()獲取并移除第一個(最低)元素;如果此 set 為空,則返回 null。
E pollLast()獲取并移除最后一個(最高)元素;如果此 set 為空,則返回 null。
獲?。?/p>
Iterator
E first()返回此 set 中當(dāng)前第一個(最低)元素。
E last()返回此 set 中當(dāng)前最后一個(最高)元素。
int size()返回 set 中的元素數(shù)(set 的容量)。
判斷:
boolean isEmpty()如果此 set 不包含任何元素,則返回 true。
boolean contains(Object o)如果此 set 包含指定的元素,則返回 true。
**Map:將鍵映射到值的對象。Map集合沒有迭代器!Map集合特點(diǎn):該集合存儲鍵值對。而且鍵是唯一的。
|--->方法摘要:
|--->添加:
V put(K key, V value)將指定的值與此映射中的指定鍵關(guān)聯(lián)(可選操作)。
void putAll(Map extends K,? extends V> m)從指定映射中將所有映射關(guān)系復(fù)制到此映射中
|--->刪除:
void clear()從此映射中移除所有映射關(guān)系(可選操作)。
V remove(Object key)如果存在一個鍵的映射關(guān)系,則將其從此映射中移除(可選操作)。
|--->判斷
boolean containsKey(Object key)如果此映射包含指定鍵的映射關(guān)系,則返回 true。
boolean containsValue(Object value)如果此映射將一個或多個鍵映射到指定值,則返回 true。
boolean isEmpty()如果此映射未包含鍵-值映射關(guān)系,則返回 true。
|--->獲取
int size()返回此映射中的鍵-值映射關(guān)系數(shù)。
Collection
重點(diǎn):Map集合沒有迭代器,以下是Map的兩種取出方式:
第一種:Set
返回此映射中包含的鍵的Set視圖,將Map集合中所有的鍵存入Set集合,然后再通過Set集合的 迭代器取出所有的鍵,再根據(jù)get方法獲取每個鍵的值;
第二種:Set
返回此映射中包含的映射關(guān)系的Set視圖,將Map集合中的映射關(guān)系存入到Set集合中,這個映射關(guān)系的數(shù)據(jù)類型是Map.entry,再通過Map.Entry類的方法再要取出關(guān)系里面的鍵和值
Map.Entry的方法摘要:
boolean equals(Object o)比較指定對象與此項(xiàng)的相等性。
K getKey()返回與此項(xiàng)對應(yīng)的鍵。
V getValue()返回與此項(xiàng)對應(yīng)的值。
int hashCode()返回此映射項(xiàng)的哈希碼值。
V setValue(V value)用指定的值替換與此項(xiàng)對應(yīng)的值(特有??!)。
8、Map集合和Collection集合的區(qū)別?
1,Map中一次存儲是鍵值對。
Collection中一次存儲是單個元素。
2,Map的存儲使用的put方法。
Collection存儲使用的是add方法。
3,Map集合沒有迭代器,Map的取出,是將Map轉(zhuǎn)成Set,在使用迭代器取出。
Collection取出,使用就是迭代器。
4,如果對象很多,必須使用集合存儲。
如果元素存在著映射關(guān)系,可以優(yōu)先考慮使用Map存儲或者用數(shù)組,如果沒有映射關(guān)系,可以使用Collection存儲。
8、迭代器:Iterator(Map集合沒有迭代器)(1)迭代器就是取出集合元素的方式
(2)迭代器的作用
因?yàn)槊總€集合中元素的取出方式都不一樣,于是就把元素的取出方式進(jìn)行抽取,并定義在集合內(nèi)部,這樣取出方式就可以直接訪問集合內(nèi)部的元素;
而每個容器的數(shù)據(jù)結(jié)構(gòu)不同,所以取出動作的細(xì)節(jié)也不一樣,但是有共性內(nèi)容:判斷和取出。
那么就將共性內(nèi)容進(jìn)行抽取,從而形成了接口Iterater(3)獲取迭代器的方法:
Iterator
Iterator
(3)迭代器方法:
boolean hasNext()如果仍有元素可以迭代,則返回 true。
E next()返回迭代的下一個元素。
void remove()從迭代器指向的collection中移除迭代器返回的最后一個元素(可選操作)。
9、列表迭代器:ListIterator(1)List集合特有的迭代器ListIterator是Iterator的子接口,在迭代時,不可以通過集合對象的 方法操作集合中的元素,因?yàn)闀l(fā)生ConcurrentModificationException(當(dāng)方法檢測到對象的并發(fā)修改,但不允許這種修改時,拋出此異常)(2)Iterator方法有限,只能對元素進(jìn)行判斷、取出和刪除的操作
ListIterator可以對元素進(jìn)行添加和修改動作等。
(3)獲取列表迭代器方法:
ListIterator
ListIterator
返回此列表中的元素的列表迭代器(按適當(dāng)順序),從列表中指定位置開始。
(4)列表迭代器方法:
void add(E e)將指定的元素插入列表(可選操作)。
boolean hasPrevious()如果以逆向遍歷列表,列表迭代器有多個元素,則返回 true。
int nextIndex()返回對 next 的后續(xù)調(diào)用所返回元素的索引。
E previous()返回列表中的前一個元素。
int previousIndex()返回對 previous 的后續(xù)調(diào)用所返回元素的索引。
void set(E e)用指定元素替換 next 或 previous 返回的最后一個元素(可選操作)。
10、堆棧和隊列
堆棧:先進(jìn)后出,比如杯子里的水
隊列:先進(jìn)先出,比如水管的水
11、集合類各種容器的使用注意細(xì)節(jié):
(1)迭代器:
**迭代器的next方法是自動向下取元素,要避免出現(xiàn)NoSuchElementException。
也就是在迭代循環(huán)中調(diào)用一次next方法一次就要hasNext判斷一次,比如語句
sop(it.next()+”..."+it.next())會發(fā)生上述異常。
**迭代器的next方法返回值類型是Object,所以要記得類型轉(zhuǎn)換,應(yīng)用泛型后就不用強(qiáng)轉(zhuǎn)
(2)List集合:
**List集合里面的元素因?yàn)槭菐Ы菢?biāo),所以List集合里面的元素都是有序的,另外List集合可以包含重復(fù)元素,也可以包含null。
**List集合有迭代器Iterator,還有一個特有迭代器列表ListIterator
**List集合中判斷元素是否相同都是用equals方法,無論contains、remove都依賴equals方法
比如往ArrayList集合里面存放學(xué)生,同名同年齡視為同一個人,此時就需要在學(xué)生類復(fù)寫Object類
里面的equals方法(非常重要?。∫⒁猓?(3)Set集合:
**Set接口里面存放的是元素是無序的,不可以有重復(fù)元素,可以包含null
**Set集合只有一種取出方式,就是迭代器Iterator
**Set集合功能和Collection是一致的,沒有特殊方法
|--->HashSet:
**集合里面存放的元素是無序的,唯一的 **底層數(shù)據(jù)結(jié)構(gòu)是哈希表,哈希表結(jié)構(gòu)的數(shù)據(jù)都是無序的,哈希表結(jié)構(gòu)的操作效率都高效
**線程不同步
**保證元素唯一性的原理是:通過復(fù)寫hashCode和equals方法
****如果兩元素的hashCode值相同,則繼續(xù)判斷兩元素equals是否為真
****如果兩元素的hashCode值不同,則不會調(diào)用equals方法。
**當(dāng)我們往HashSet集合存放自定義的元素時(比如學(xué)生對象),通常都要復(fù)寫hashCode和equals方法,而且hashCode和equals方法不通過我們調(diào)用,HashSet集合底層內(nèi)部自己調(diào)用,自己拿元素去比較
|--->TreeSet
**TreeSet集合可以對存放的元素進(jìn)行排序,彌補(bǔ)了Set集合元素?zé)o序的缺點(diǎn),且元素是唯一的 **底層數(shù)據(jù)結(jié)構(gòu)是二叉樹,二叉樹結(jié)構(gòu)都是有序的 **線程不同步
**TreeSet集合要求往集合里存放的元素自身具備比較性,否則會報錯
**TreeSet集合保證元素唯一性的依據(jù)是:通過compareTo或者compare方法中的來保證元素的唯一性。
TreeSet排序的第一種方式:讓元素自身具備比較性,定義元素類實(shí)現(xiàn)Compareble接口,覆蓋compare方法,此方式是元素的自然順序。
TreeSet排序的第二種方式:讓集合具備比較性
當(dāng)元素自身不具備比較性或者具備的比較性不是
我們所需要的比較性時,此時就需要讓集合具備自定義的比較性。
那如何讓集合自身具備比較性呢?
可在集合初始化時,就讓集合具備比較方式。
即定義一個類,實(shí)現(xiàn)Comparator接口,覆蓋compare方法。
注:
**判斷元素唯一時,當(dāng)主要條件一樣時,判斷次要條件
**兩種排序方式都在時,以比較器為主??!
(4)Map集合:
|--Hashtable
底層是哈希表結(jié)構(gòu)
線程安全的,并且鍵和值不能為null。
|--HashMap
底層是哈希表結(jié)構(gòu)
線程不安全的,鍵和值可以為null。
|--LinkedHashMap
底層是鏈表和哈希表
線程不安全
|--TreeMap
底層是二叉樹
線程不安全的
12、如果你想將一組對象按一定順序存取,在不考慮并發(fā)訪問的情況下會使用____C_____ ,反之則會使用____A_____;如果你想存儲一組無序但唯一的對象,你會使用___B______;
如果你想按關(guān)鍵字對對象進(jìn)行存取,在不考慮并發(fā)訪問的情況下會使用___D______ ,反之則會使用_____E____。A.Vector B.HashSet C.ArrayList D.HashMap E.Hashtable
13、泛型:
(1)為什么會出現(xiàn)泛型?
因?yàn)榧洗娣诺臄?shù)據(jù)類型不固定,故往集合里面存放元素時,存在安全隱患,如果在定義集合時,可以想定義數(shù)組一樣指定數(shù)據(jù)類型,那么就可以解決該類安全問題。
JDK1.5后出現(xiàn)了泛型,用于解決集合框架的安全問題。
泛型是一個類型安全機(jī)制。
(2)泛型定義格式:通過<>來定義要操作的引用數(shù)據(jù)類型
ArrayList
**將運(yùn)行時期出現(xiàn)的ClassCastException(類型轉(zhuǎn)換異常)問題轉(zhuǎn)移到編譯時期;
**避免了強(qiáng)制轉(zhuǎn)換的麻煩
(4)什么時候定義泛型?
泛型在集合框架中很常見,只要見到<>就要定義泛型。其實(shí)<>就是用來接收類型的。
當(dāng)使用集合時,將集合中要存儲的數(shù)據(jù)類型作為參數(shù)傳遞到<>中即可
(5)泛型的形式
**泛型類:即自定義泛型類
A:當(dāng)類中要操作的引用數(shù)據(jù)類型不確定時,早起定義Object來完成擴(kuò)展,現(xiàn)在定義泛型來完成B:局限性:泛型類定義的泛型,在整個類中有效,如果該泛型類的方法被調(diào)用,當(dāng)泛型類的對象明確要操作的類型后,所有要操作的類型就被固定。
**泛型方法:泛型放在返回值前面,修飾符的后面
A:為了避免泛型類的局限性,讓不同方法可以操作不同的類型,而且類型還不確定,則可以將泛型定義在方法上
B:特殊之處:靜態(tài)方法不可以反問類上定義的泛型
如果靜態(tài)方法操作的應(yīng)用數(shù)據(jù)類型不確定,可以講泛型定義在靜態(tài)方法上
**泛型接口:
當(dāng)泛型定義在接口上時,則子類中要指定實(shí)現(xiàn)接口類型,同時還可以子類也可以定義為泛型類
(6)泛型的高級應(yīng)用:?通配符
**當(dāng)指定兩種泛型的集合,則迭代時也要定義兩種泛型的迭代器,麻煩,此時可通過將迭代器的泛型
改為?,如Iterator> it=al.iterator();
**兩種泛型限定
向上限定: ? extends E;E可以接收E類型或者E的子類
向下限定: ? super E;E可以接收E類型或者E的父類
14、高級for循環(huán)
(1)JDK1.5新特性,代替迭代器使用時的不爽,簡化書寫,底層原理是迭代器凡是支持迭代器的都支持高級for循環(huán)
高級for循環(huán),只用于集合和數(shù)組的遍歷,集合只能用Collection不能用Map集合 只能把Map集合轉(zhuǎn)化成Set集合,才能用for循環(huán)。
(2)格式
for(數(shù)據(jù)類型 變量名:被遍歷的集合(Collection)或者數(shù)組)
{
}
(3)局限性:
必須要有遍歷的目標(biāo)
對集合或者數(shù)組進(jìn)行遍歷時,只能獲取集合元素,不能對集合元素進(jìn)行操作
迭代器除了遍歷,還可以進(jìn)行remove操作集合中的元素
列表迭代器還可以在遍歷過程中進(jìn)行增刪改查的操作
(4)傳統(tǒng)for循環(huán)和高級for循環(huán)的區(qū)別
高級for循環(huán)有一個局限性,就是必須要有遍歷的目標(biāo)(集合或者數(shù)組)
遍歷數(shù)組時建議使用傳統(tǒng)for循環(huán),因?yàn)榭梢远x角標(biāo),比如打印100次helloworld時用傳統(tǒng)for循環(huán)方便
15、可變參數(shù)
(1)數(shù)組的可變參數(shù)
格式:
int...arr(3)方法的可變參數(shù)
格式:
public static void show(String str,int...arr)
{
}
注意:可變參數(shù)一定要放在參數(shù)列表的最后面
16、靜態(tài)導(dǎo)入:
**import static java.util.Arrays.* 導(dǎo)入的是Arrays這個類中所有的靜態(tài)方法
**當(dāng)類名重名時,需要制定具體的報名
**當(dāng)方法重名時,需要制定具體所屬的對象或者類
17、Collections類:
(1)此類完全由在 collection 上進(jìn)行操作或返回 collection 的靜態(tài)方法組成。
(2)靜態(tài)方法摘要:
static
將所有指定元素添加到指定 collection 中。
static
使用指定元素替換指定列表中的所有元素。
static
使用另一個值替換列表中出現(xiàn)的所有某一指定值。
static void reverse(List> list)
反轉(zhuǎn)指定列表中元素的順序。
static
返回一個比較器,它強(qiáng)行逆轉(zhuǎn)實(shí)現(xiàn)了 Comparable 接口的對象 collection 的自然順序
static
返回一個比較器,它強(qiáng)行逆轉(zhuǎn)指定比較器的順序。
(3)Collections類特牛的方法:
集合有一個共同的缺點(diǎn),那就是線程不安全,被多線程操作時,容易出現(xiàn)問題,雖然可以自己加鎖
但是麻煩。Collections提供特牛的方法,就是給它一個不同步的集合,它返回一個同步的安全的集合static
返回指定 collection 支持的同步(線程安全的)collection。
static
返回指定列表支持的同步(線程安全的)列表。
static
返回由指定映射支持的同步(線程安全的)映射。
static
返回指定 set 支持的同步(線程安全的)set。
static
返回指定有序映射支持的同步(線程安全的)有序映射。
static
返回指定有序 set 支持的同步(線程安全的)有序 set。
18、Arrays類:
此類包含用來操作數(shù)組(比如排序和搜索)的各種方法。里面都是靜態(tài)方法。
如果指定數(shù)組引用為 null,則此類中的方法都會拋出 NullPointerException。
(1)靜態(tài)方法摘要:
static
返回一個受指定數(shù)組支持的固定大小的列表。
注意:
A:該方法將一個數(shù)組變成集合后,不可以使用集合的增刪方法,因?yàn)閿?shù)組的長度是固定的!
如果增刪,則發(fā)生UnsupportedOprationException(不支持操作異常)
B:如果數(shù)組中的元素都是基本數(shù)據(jù)類型,則該數(shù)組變成集合時,會將該數(shù)組作為集合的一個
元素出入集合C:如果數(shù)組中的元素都是對象,如String,那么數(shù)組變成集合后,數(shù)組中的元素就直接轉(zhuǎn)成集合中的元素
19、數(shù)組變集合以及集合變數(shù)組的對比:
(1)數(shù)組變集合:
方法:static
好處:可以使用集合的思想和方法操作數(shù)組中的元素,數(shù)組是一個對象,但是數(shù)組中的功能很少
(2)集合變數(shù)組:
方法:Collction中的toArray方法
好處:可以限定對集合元素的操作,防止對集合的元素進(jìn)行增刪,因?yàn)閿?shù)組長度是固定的。
20、Collections類和Arrays類的使用。(重點(diǎn))A:Collections
排序
二分查找
發(fā)轉(zhuǎn)
B:Arrays
把數(shù)組變成字符串輸出
排序
二分查找
21、System:
(1)描述系統(tǒng)信息的類
(2)該類沒有構(gòu)造方法,該類的方法和屬性都是靜態(tài)的(3)字段摘要:
static InputStream in “標(biāo)準(zhǔn)”輸入流。
static PrintStream out “標(biāo)準(zhǔn)”輸出流。
(4)方法摘要:
static void exit(int status)終止當(dāng)前正在運(yùn)行的 Java 虛擬機(jī)。
static void gc()運(yùn)行垃圾回收器。
static Properties getProperties()確定當(dāng)前的系統(tǒng)屬性
static String getProperty(String key)獲取指定鍵指示的系統(tǒng)屬性。
static String getProperty(String key, String def)獲取用指定鍵描述的系統(tǒng)屬性。
static void setIn(InputStream in)重新分配“標(biāo)準(zhǔn)”輸入流。
static void setOut(PrintStream out)重新分配“標(biāo)準(zhǔn)”輸出流。
static void setProperties(Properties props)將系統(tǒng)屬性設(shè)置為 Properties 參數(shù)。
static String setProperty(String key, String value)設(shè)置指定鍵指示的系統(tǒng)屬性。
22、Runtime:(1)每個 Java 應(yīng)用程序都有一個 Runtime 類實(shí)例,使應(yīng)用程序能夠與其運(yùn)行的環(huán)境相連接。
第三篇:java學(xué)習(xí)筆記
jdk(java development kit)
有如下公司或組織開發(fā)jdk
sun jdk
ibm jdk
bea jrocket
gun jdk
其中ibm的jdk包含的jvm(java virtual machine)運(yùn)行效率要比sun jdk包含的jvm高出許多。而專門運(yùn)行在x86平臺的jrocket在服務(wù)端運(yùn)行效率也要比sun jdk好很多。但不管怎么說,我們還是需要先把sun jdk掌握好。
1、jdk的下載和安裝
jdk又叫做j2se(java2 sdk standard edition),可以從sun的java網(wǎng)站上下載到,http://java.sun.com/j2se/downloads.html,jdk當(dāng)前最新的版本是j2sdk1.4.2,建議下載該版本的jdk,下載頁面在這里:http://java.sun.com/j2se/1.4.2/download.html。
下載好的jdk是一個可執(zhí)行安裝程序,默認(rèn)安裝完畢后會在c:program filesjava目錄下安裝一套jre(供瀏覽器來使用),在c:j2sdk1.4.2下安裝一套jdk(也包括一套jre)。然后我們需要在環(huán)境變量path的最前面增加java的路徑c:j2sdk1.4.2bin。這樣jdk就安裝好了。
2、java documentation
java編程手冊,java核心所在3、java 應(yīng)用服務(wù)器
a、tomcat
b、ibm webshpere
c、bea weblogic
d、免費(fèi) jboss4、java應(yīng)用的運(yùn)行環(huán)境
應(yīng)用服務(wù)器(app server)
app server是運(yùn)行java企業(yè)組件的平臺,構(gòu)成了應(yīng)用軟件的主要運(yùn)行環(huán)境。當(dāng)前主流的app server是bea公司的weblogic server和ibm公司的websphere以及免費(fèi)的jboss,選擇其中一個進(jìn)行學(xué)習(xí)就可以了,個人推薦weblogic,因?yàn)樗捏w系結(jié)構(gòu)更加干凈,開發(fā)和部署更加方便,是java企業(yè)軟件開發(fā)人員首選的開發(fā)平臺。下面簡要介紹幾種常用的app server:
1、tomcat
tomcat嚴(yán)格意義上并不是一個真正的app server,它只是一個可以支持運(yùn)行serlvet/jsp的web容器,不過tomcat也擴(kuò)展了一些app server的功能,如jndi,數(shù)據(jù)庫連接池,用戶事務(wù)處理等等。tomcat被非常廣泛的應(yīng)用在中小規(guī)模的java web應(yīng)用中,因此本文做一點(diǎn)下載、安裝和配置tomcat的介紹:
tomcat是apache組織下jakarta項(xiàng)目下的一個子項(xiàng)目,它的主網(wǎng)站是:http://jakarta.apache.org/tomcat/,tomcat最新版本是tomcat4.1.27,軟件下載的連接是:http://
在啟用這兩個管理工具之前,先需要手工配置一下管理員用戶和口令。用一個文本工具打開catalina_homeconftomcat-users.xml這個文件,加入如下幾行:
這樣用戶“robbin”就具備了超級管理員權(quán)限。重新啟動tomcat以后,你就可以使用該用戶來登陸如上的兩個管理工具,通過web方式進(jìn)行tomcat的配置和管理了。
2、bea weblogic
weblogic可以到bea的網(wǎng)站上免費(fèi)注冊之后下載到最新的weblogic8.1企業(yè)版,license可以免費(fèi)使用1年時間,其實(shí)這已經(jīng)完全足夠了。weblogic的下載連接:http://commerce.bea.com/index.jsp,.../edocs.bea.com/。
3、ibm webshpere
websphere同樣可以下載到免費(fèi)的試用版本,到ibm的developerworks網(wǎng)站可以看到websphere試用產(chǎn)品的下載和相關(guān)的websphere的資料,developerworks中文網(wǎng)站的連接是:http://。
4、jboss
jboss是免費(fèi)開源的app server,可以免費(fèi)的從jboss網(wǎng)站下載:http://,然...n.com/idea.html
四、java應(yīng)用的運(yùn)行環(huán)境
java的應(yīng)用可以簡單分為以下幾個方面:
1、java的桌面應(yīng)用
桌面應(yīng)用一般僅僅需要jre的支持就足夠了。
2、java web應(yīng)用
java的web應(yīng)用至少需要安裝jdk和一個web容器(例如tomcat),以及一個多用戶數(shù)據(jù)庫,web應(yīng)用至少分為三層:
browser層:瀏覽器顯示用戶頁面
web層:運(yùn)行servlet/jsp
db層:后端數(shù)據(jù)庫,向java程序提供數(shù)據(jù)訪問服務(wù)
3、java企業(yè)級應(yīng)用
企業(yè)級應(yīng)用比較復(fù)雜,可以擴(kuò)展到n層,最簡單情況會分為4層:
browser層:瀏覽器顯示用戶頁面
client層:java客戶端圖形程序(或者嵌入式設(shè)備的程序)直接和web層或者ejb層交互
web層:運(yùn)行servlet/jsp
ejb層:運(yùn)行ejb,完成業(yè)務(wù)邏輯運(yùn)算
db層:后端數(shù)據(jù)庫,向java程序提供數(shù)據(jù)訪問服務(wù)
4、java嵌入式應(yīng)用
java嵌入式應(yīng)用是一個方興未艾的領(lǐng)域,從事嵌入式開發(fā),需要從sun下載j2me開發(fā)包,j2me包含了嵌入式設(shè)備專用虛擬機(jī)kvm,和普通的jdk中包含的jvm有所不同。另外還需要到特定的嵌入式廠商那里下載模擬器。
第四篇:Java基礎(chǔ)學(xué)習(xí)心得筆記
千鋒教育004km.cn 精品課程 全程面授
Java基礎(chǔ)學(xué)習(xí)心得筆記
對于很多只會C語言的初學(xué)者而言,面對java基礎(chǔ)語法學(xué)習(xí),反而感覺很難,其實(shí)其中最大的問題不是語法難,而是一種編程思想的轉(zhuǎn)變。面向過程就是把你的代碼封裝成函數(shù),然后依次去做一件事情,面向過程是把你要做的事情抽象成對象,告訴對象去做。所以要想學(xué)好java入門,必須知道類和對象的概念。
類是對生活中事物的抽象描述,比如人類,動物類,交通工具類;對象即是對類的具體實(shí)例化,比如張三是人,貓是動物,飛機(jī)是交通工具(對象-----類)。Java基礎(chǔ)入門學(xué)習(xí)路線可以總結(jié)為四步走:
1.java開發(fā)環(huán)境的搭建;
2.java初級之基礎(chǔ)語法學(xué)習(xí)(80%類似C語言);3.java中級之面向?qū)ο缶幊虒W(xué)習(xí)(重點(diǎn)); 4.java中級之應(yīng)用編程學(xué)習(xí)。
第一步:JDK軟件開發(fā)包時java軟件開發(fā)環(huán)境,包括jre運(yùn)行環(huán)境和jvm虛擬機(jī),在oricle官網(wǎng)下載javaSE版本JDK包;配置好環(huán)境變量就可以使用了。
第二步:java初級語法學(xué)習(xí),1.基本數(shù)據(jù)類型整形,字符型,字節(jié)型,長整形,短整形,浮點(diǎn)型,雙精度,布爾型;
千鋒教育-中國IT職業(yè)教育領(lǐng)先品牌
千鋒教育004km.cn 精品課程 全程面授
2.運(yùn)算符+,-,*,/,%等; 3.控制流(while,switch,if else);4.數(shù)組的定義方式。
此階段基本無難度,只要了解練習(xí)例題。
第三步:java面向?qū)ο髮W(xué)習(xí),1.類和對象;
2.java語言三大特性,封裝、繼承、多態(tài);
3.一些關(guān)鍵字學(xué)習(xí)(static,final,abstract,extends)等。這是重點(diǎn),大家根據(jù)知識點(diǎn)一步步研究學(xué)習(xí)才是關(guān)鍵。
第四步:java應(yīng)用編程,例如:文件IO,集合(類似C語言數(shù)據(jù)結(jié)構(gòu)),異常處理,線程,網(wǎng)絡(luò),JDBC數(shù)據(jù)庫操作等,都是掌握面向?qū)ο笠院?,在查找不同的類使用類中不同的方法達(dá)到應(yīng)用的效果,所以并不會很難。等基礎(chǔ)語法掌握了就可以繼續(xù)后面框架學(xué)習(xí)(java web方向,android學(xué)習(xí)),相信明確思路你會豁然開朗,更有學(xué)習(xí)動力。
以上沒有具體的實(shí)例和知識點(diǎn)講解,分享的只是完全沒接觸過java的初學(xué)者自學(xué)java的思路和學(xué)習(xí)的流程,應(yīng)該把握的重點(diǎn),希望大家有所幫助。
如果你想學(xué)好Java,找一家靠譜的培訓(xùn)機(jī)構(gòu),能讓你的學(xué)習(xí)事半功倍。
千鋒教育-中國IT職業(yè)教育領(lǐng)先品牌
千鋒教育004km.cn 精品課程 全程面授
千鋒教育的Java培訓(xùn)對互聯(lián)網(wǎng)的歷程及發(fā)展有著極為遠(yuǎn)見的規(guī)劃,因此結(jié)合大數(shù)據(jù)潮流,融合最前沿資訊,對接名企最新需求,對Java的發(fā)展及潮流方向都有一個很好的把控,讓學(xué)員贏在現(xiàn)在的同時,更讓學(xué)員贏在未來。
千鋒教育力造IT培訓(xùn)領(lǐng)導(dǎo)品牌,學(xué)員百分之九十以上都是大專以上學(xué)生,力求為你營造最優(yōu)質(zhì)的學(xué)習(xí)環(huán)境。千鋒教育現(xiàn)在更有0學(xué)費(fèi)入學(xué)、2周免費(fèi)試聽、跨學(xué)科周末班限時免費(fèi)送活動,一次報名,學(xué)習(xí)雙技能,如同打了五折。歡迎你前來咨詢,試聽。
千鋒教育-中國IT職業(yè)教育領(lǐng)先品牌
千鋒教育004km.cn 精品課程 全程面授
千鋒教育-中國IT職業(yè)教育領(lǐng)先品牌
第五篇:java學(xué)習(xí)筆記(更新)
1.JSP內(nèi)置對象分類
與Servlet有關(guān)的隱含對象
page、config
與Input/Output有關(guān)的隱含對象
out、request、response
JSP執(zhí)行時,提供有關(guān)Context的隱含對象
session、application、pageContext 與Error有關(guān)的隱含對象
exception
2.get與post區(qū)別
get方式:將表單內(nèi)容經(jīng)過編碼之后,通過URL發(fā)送,使用get方式發(fā)送時有255個字符的限制(可以在地址欄里看到方式和地點(diǎn))
post方式:將表單的內(nèi)容通過http發(fā)送,post沒有字符長度的限制(在地址欄里看不到表單提交的信息
3.forward與sendredirect區(qū)別 服務(wù)器端跳轉(zhuǎn)
使用
使用服務(wù)器端跳轉(zhuǎn),可以通過
response.sendRedirect(“uri”);地址欄改變的跳轉(zhuǎn)
所有代碼執(zhí)行完畢之后再跳轉(zhuǎn)
使用response時,不能保存request屬性
使用客戶端跳轉(zhuǎn),可以通過重寫URL的方式來傳遞參數(shù) 4.JSP內(nèi)置對象session
session對象用來存儲有關(guān)用戶會話的所有信息直到它的生命周期超時或被人為釋放掉為止。
設(shè)置session session.setAttribute(“name”, “admin”);根據(jù)名稱去獲取session中存放對象的值
String name =(String)session.getAttribute(“name”);根據(jù)名稱去刪除session中存放對象的值 session.removeAttribute(“name”);用戶注銷功能的實(shí)現(xiàn) session.invalidate();5.JDBC API JDBC API可做三件事:與數(shù)據(jù)庫建立連接、執(zhí)行SQL語句、處理結(jié)果 DriverManager :依據(jù)數(shù)據(jù)庫的不同,管理JDBC驅(qū)動 Connection :負(fù)責(zé)連接數(shù)據(jù)庫并擔(dān)任傳送數(shù)據(jù)的任務(wù)
Statement(PreparedStatement):由 Connection 產(chǎn)生、負(fù)責(zé)執(zhí)行SQL語句 ResultSet:負(fù)責(zé)保存Statement執(zhí)行后所產(chǎn)生的查詢結(jié)果
JDBC應(yīng)用開始->裝入JDBC驅(qū)動程序
->創(chuàng)建與數(shù)據(jù)庫的連接->創(chuàng)建語句對象——Statement或PreparedStatement->利用語句對象執(zhí)行SQL語句,得到結(jié)果
->處理結(jié)果 JDBC應(yīng)用結(jié)束 6.MVC設(shè)計模式
模型(Model)JavaBean 代表應(yīng)用程序狀態(tài)和業(yè)務(wù)邏輯
視圖(View)JSP 提供可交互的客戶界面,向客戶顯示模型數(shù)據(jù)
控制器(Controller)Servlet 根據(jù)客戶的請求來操縱模型,并把結(jié)果經(jīng)由視圖展現(xiàn)給客戶
Model I設(shè)計模式
JSP+JavaBean(View + Model)
Model II設(shè)計模式
JSP+JavaBean+servlet(View + Model+controller)
Model I和Model II的對比
Model I缺少控制器(Controller),不易維護(hù)和擴(kuò)展 Model I開發(fā)速度快,適用于開發(fā)中、小型項(xiàng)目
Model II 代碼的重用性 有利于開發(fā)的分工
各司其職、互不干涉 7.EL表達(dá)式
由于jsp標(biāo)準(zhǔn)動作的局限,一般是操作JavaBean的屬性
JavaBean的屬性只能為基本數(shù)據(jù)類型不能進(jìn)行邏輯操作,而el卻可以精確的訪問存儲對象,Bean屬性的簡略記法,空值取代錯誤消息 優(yōu)點(diǎn)
代替復(fù)雜代碼,省去條件判斷 訪問Bean的屬性 Bean屬性的簡略記法
以輸出MVC中的內(nèi)容,代碼簡單 8.EL隱式對象
pageScope:范圍和JSP的page相同,只限于當(dāng)前頁面 requestScope:范圍和JSP的page相同,范圍限于一次請求 sessionScope:范圍和JSP的session相同,范圍為一次會話
applicationScope:從服務(wù)器一開始執(zhí)行服務(wù),到服務(wù)器關(guān)閉為止 9.jsp中動態(tài)include和靜態(tài)的include 區(qū)別
動態(tài)INCLUDE總是會檢查所含文件中的變化,適合用于包含動態(tài)頁面,并且可以帶參數(shù)。
靜態(tài)include偽碼實(shí)現(xiàn),不會檢查所含文件的變化,適用于包含靜態(tài)頁面 10.Servlet和JSP的關(guān)系
Servlet是JSP的早期版本,在JSP中,更加注重頁面的表現(xiàn),而在Servlet中則更注重業(yè)務(wù)邏輯的實(shí)現(xiàn)。
同時,JSP只能處理瀏覽器的請求,而Servlet則可以處理一個客戶端的應(yīng)用程序請求。因此,Servlet加強(qiáng)了Web服務(wù)器的功能。10.Servlet的生命周期
Servlet是服務(wù)器端運(yùn)行的。Servlet是javax.servlet包中HttpServlet類的子類,由服務(wù)器完成該子類的創(chuàng)建和初始化。
Servlet的生命周期主要由3個過程組成。
1、init()方法:服務(wù)器初始化Servlet。
2、service()方法:初始化完畢,Servlet對象調(diào)用該方法相應(yīng)客戶的請求。
3、destroy()方法:調(diào)用該方法消滅Servlet對象。其中,init()方法只在Servlet第一次被請求加載的時候被調(diào)用一次,當(dāng)有客戶再請求Servlet服務(wù)時,Web服務(wù)器將啟動一個新的線程,在該線程中,調(diào)用service方法相應(yīng)客戶的請求。11.JSP 6種基本動作
jsp:include:在頁面被請求的時候引入一個文件。jsp:useBean:尋找或者實(shí)例化一個JavaBean。jsp:setProperty:設(shè)置JavaBean的屬性。jsp:getProperty:輸出某個JavaBean的屬性。jsp:forward:把請求轉(zhuǎn)到一個新的頁面。
jsp:plugin:根據(jù)瀏覽器類型為Java插件生成OBJECT或EMBED標(biāo)記
12.Request對象的主要方法:
setAttribute(String name,Object):設(shè)置名字為name的request的參數(shù)值 getAttribute(String name):返回由name指定的屬性值
getAttributeNames():返回request對象所有屬性的名字集合,結(jié)果是一個枚舉的實(shí)例 getCookies():返回客戶端的所有Cookie對象,結(jié)果是一個Cookie數(shù)組 getCharacterEncoding():返回請求中的字符編碼方式 getContentLength():返回請求的Body的長度
getHeader(String name):獲得HTTP協(xié)議定義的文件頭信息
getHeaders(String name):返回指定名字的request Header的所有值,結(jié)果是一個枚舉的實(shí)例
getHeaderNames():返回所以request Header的名字,結(jié)果是一個枚舉的實(shí)例 getInputStream():返回請求的輸入流,用于獲得請求中的數(shù)據(jù) getMethod():獲得客戶端向服務(wù)器端傳送數(shù)據(jù)的方法
getParameter(String name):獲得客戶端傳送給服務(wù)器端的有name指定的參數(shù)值 getParameterNames():獲得客戶端傳送給服務(wù)器端的所有參數(shù)的名字,結(jié)果是一個枚舉的實(shí)例
getParameterValues(String name):獲得有name指定的參數(shù)的所有值 getProtocol():獲取客戶端向服務(wù)器端傳送數(shù)據(jù)所依據(jù)的協(xié)議名稱 getQueryString():獲得查詢字符串
getRequestURI():獲取發(fā)出請求字符串的客戶端地址 getRemoteAddr():獲取客戶端的IP地址 getRemoteHost():獲取客戶端的名字
getSession([Boolean create]):返回和請求相關(guān)Session getServerName():獲取服務(wù)器的名字
getServletPath():獲取客戶端所請求的腳本文件的路徑 getServerPort():獲取服務(wù)器的端口號
removeAttribute(String name):刪除請求中的一個屬性 13.會話跟蹤技術(shù)
Session 隱藏表單域 URL重寫 Cookie使用 14.cookie的使用
cookie是一段字符串,由HTTP支持,在客戶端可以永久保存.寫入(硬盤).每次請求,響應(yīng)中都會為cookie留有空間.Cookie cookie=new Cookie(“name”,cookie);//必須指定cookie的鍵與值,且必須為字符串.response.addcookie(cookie);
cookie.setMaxAge(3600);//以秒為單位.讀取客戶端發(fā)送過來的cookie,返回值類型為: cookie數(shù)組
request.getCookies();循環(huán)讀取鍵與值.小常識:(1).一個網(wǎng)站最多向一個客戶端寫20個cookie.(2).一個客戶端最多接收300個cookie.