《Java 程序設(shè)計(jì)基礎(chǔ)》 課件 第5-9章- String 字符串-抽象類和接口_第1頁(yè)
《Java 程序設(shè)計(jì)基礎(chǔ)》 課件 第5-9章- String 字符串-抽象類和接口_第2頁(yè)
《Java 程序設(shè)計(jì)基礎(chǔ)》 課件 第5-9章- String 字符串-抽象類和接口_第3頁(yè)
《Java 程序設(shè)計(jì)基礎(chǔ)》 課件 第5-9章- String 字符串-抽象類和接口_第4頁(yè)
《Java 程序設(shè)計(jì)基礎(chǔ)》 課件 第5-9章- String 字符串-抽象類和接口_第5頁(yè)
已閱讀5頁(yè),還剩137頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Java程序設(shè)計(jì)基礎(chǔ)String字符串String字符串主要內(nèi)容15.1JavaAPI及API文檔5.2String類(重點(diǎn))5.3StringBuffer類(重點(diǎn))5.4其他工具類教學(xué)目標(biāo)2能通過查閱API文檔學(xué)習(xí)類及方法的基本作用能準(zhǔn)確使用String類中的常用方法及其作用能理解String的不可變性能準(zhǔn)確區(qū)分String的兩種“相等”比較能準(zhǔn)確區(qū)分StringBuffer類和String類的特點(diǎn)能正確的使用構(gòu)造方法創(chuàng)建String、StringBuffer及StringBuilder對(duì)象能理解StringBuffer的內(nèi)存模型能正確使用Date、SimpleDateFormat等常用工具類JavaAPI3Java給程序員提供了JavaAPI(ApplicationProgrammingInterface,應(yīng)用程序編程接口)文檔,供Java程序員隨時(shí)查閱。API文檔描述了類庫(kù)中的類及其方法的輸入、輸出和功能,程序員依據(jù)文檔直接調(diào)用,無(wú)須關(guān)注實(shí)現(xiàn)細(xì)節(jié)。在使用JavaAPI文檔時(shí),需要注意API文檔的版本號(hào)要和JDK的版本號(hào)一致,否則可能出現(xiàn)文檔與實(shí)際使用的類庫(kù)不一致的情況。API文檔4以JDK8為例,JavaAPI文檔的文檔結(jié)構(gòu)API文檔5如果要查找String字符串類的其他方法,可以在“索引”處輸入String,在彈出的對(duì)話框(見下圖)中選擇相關(guān)主題,單擊“顯示”按鈕,就會(huì)顯示String類的相關(guān)內(nèi)容String簡(jiǎn)介6String類表示字符串,Java程序中的所有字符串(例如“藍(lán)橋”)都作為此類的對(duì)象String類不是基本數(shù)據(jù)類型,它是一個(gè)類。因?yàn)閷?duì)象的初始化默認(rèn)值是null,所以String類對(duì)象的初始化默認(rèn)值也是nullString是一種特殊的對(duì)象String字符串是常量,字符串的值在創(chuàng)建之后不能更改String類是final修飾的最終類,因此不能被繼承創(chuàng)建String對(duì)象7String(Strings):創(chuàng)建一個(gè)新的String對(duì)象,使其內(nèi)容為參數(shù)s中的字符序列String(char[]value):創(chuàng)建一個(gè)新的String對(duì)象,使其內(nèi)容為參數(shù)value中的字符序列String(char[]value,intoffset,intcount):創(chuàng)建一個(gè)新的String對(duì)象,其內(nèi)容為取自字符數(shù)組參數(shù)value的一個(gè)子序列。offset參數(shù)是子數(shù)組第一個(gè)字符的索引(從0開始建立索引),count參數(shù)指定子數(shù)組的長(zhǎng)度創(chuàng)建String對(duì)象8示例StringstuName1=newString("王云");char[]charArray={'劉','靜','濤'};StringstuName2=newString(charArray);StringstuName3=newString(charArray,1,2);//從'靜'字開始,截取2個(gè)字符,結(jié)果是“靜濤”不可變特性9String字符串是常量,字符串的值在創(chuàng)建之后不能更改。concat(Stringstr)方法實(shí)際創(chuàng)建了一個(gè)新String字符串,用來(lái)存放stuName1字符串加上“同學(xué)”的結(jié)果,而不是在原來(lái)stuName1字符串的后面增加內(nèi)容,對(duì)于stuName1而言,它是常量,內(nèi)容并沒有變化比較相等10比較字符串常用的兩個(gè)方法是運(yùn)算符==和String類的equals方法使用“==”比較兩個(gè)字符串,是比較兩個(gè)對(duì)象在內(nèi)存中的地址是否一致,本質(zhì)上就是判斷兩個(gè)變量是否指向同一個(gè)對(duì)象,如果是則返回true,否則返回falseString類的equals方法則是比較兩個(gè)String字符串的內(nèi)容是否一致,返回值也是一個(gè)布爾類型。常用方法11publiccharcharAt(intindex)返回index指定的索引處的字符publicintlength()返回此字符串的長(zhǎng)度。這里需要和獲取數(shù)組長(zhǎng)度區(qū)別開,獲取數(shù)組長(zhǎng)度是通過數(shù)組名.length獲取的publicintindexOf(Stringstr)返回指定子字符串str在此字符串中第一次出現(xiàn)處的索引。常用方法12publicintindexOf(Stringstr,intfromIndex)返回指定子字符串str在此字符串中第一次出現(xiàn)處的索引,從指定的索引fromIndex處開始搜索publicbooleanequalsIgnoreCase(Stringanother)將此String與另一個(gè)字符串a(chǎn)nother比較,比較時(shí)不區(qū)分大小寫publicStringreplace(charoldChar,charnewChar)返回一個(gè)新的字符串,它是通過用newChar替換此字符串中出現(xiàn)的所有oldChar得到的。這里再重申一下,String類方法中的索引都是從0開始編號(hào)的。常用方法13publicbooleanstartsWith(Stringprefix)判斷此字符串是否以prefix指定的前綴開始publicbooleanendsWith(Stringsuffix)判斷此字符串是否以suffix指定的后綴結(jié)束publicStringtoUpperCase()將此String中的所有字符都轉(zhuǎn)換為大寫常用方法14publicStringtoLowerCase()將此String中的所有字符都轉(zhuǎn)換為小寫publicStringsubstring(intbeginIndex)返回一個(gè)從beginIndex開始到結(jié)尾的新的子字符串publicStringsubstring(intbeginIndex,intendIndex)返回一個(gè)從beginIndex開始到endIndex結(jié)尾(不含endIndex所指字符)的新的子字符串常用方法15publicStringtrim()返回字符串的副本,忽略原字符串前后的空格publicString[]split(Stringregex)通過regex指定的分隔符分隔字符串,返回分隔后的字符串?dāng)?shù)組。常用方法16publicstaticStringvalueOf(基本數(shù)據(jù)類型參數(shù))返回基本數(shù)據(jù)類型參數(shù)的字符串表示形式,例如:publicstaticStringvalueOf(inti)publicstaticStringvalueOf(doubled)常用方法17前兩個(gè)方法是String類的靜態(tài)方法,關(guān)于“靜態(tài)”的內(nèi)容將會(huì)在后面的課程詳細(xì)介紹,這里需要大家注意的是,靜態(tài)方法是通過類名.方法名直接調(diào)用的,例如:Stringresult=String.valueOf(100);//將int型100轉(zhuǎn)換為字符串"100"StringBuffer簡(jiǎn)介18StringBuffer字符串代表的是可變的字符序列,可以對(duì)字符串對(duì)象的內(nèi)容進(jìn)行修改StringBuffer類最常用的構(gòu)造方法。StringBuffer():構(gòu)造一個(gè)空白的字符串緩沖區(qū),其初始容量為16個(gè)字符。StringBuffer(Stringstr):構(gòu)造一個(gè)字符串緩沖區(qū),并將其內(nèi)容初始化為指定的字符串內(nèi)容。StringBuffer簡(jiǎn)介19通過StringBuffer類的構(gòu)造方法創(chuàng)建StringBuffer字符串

StringBufferstrB1=newStringBuffer();System.out.println(strB1.length());以上通過strB1.length()返回的字符串長(zhǎng)度是0。但實(shí)際上,strB1的底層創(chuàng)建了一個(gè)長(zhǎng)度為16的字符數(shù)組,為接收字符串內(nèi)容做準(zhǔn)備。StringBufferstrB2=newStringBuffer("柳海龍");System.out.println(strB2.length());通過strB2.length()返回長(zhǎng)度是3,實(shí)際在底層創(chuàng)建了一個(gè)長(zhǎng)度為3+16的字符數(shù)組追加和插入20publicStringBufferappend(Stringstr)將str指定的字符串追加到此字符序列的末尾publicStringBufferappend(StringBufferstr)將str指定的StringBuffer字符串追加到此序列的末尾publicStringBufferappend(char[]str)將str指定的字符數(shù)組追加到此序列的末尾。追加和插入21publicStringBufferappend(char[]str,intoffset,intlen)自索引offset開始截取str的len個(gè)字符追加到此序列中。publicStringBufferappend(doubled)將double類型的變量d的字符串表示形式追加到此序列的末尾。publicStringBufferappend(Objectobj)將參數(shù)obj的字符串表示形式追加到此序列的末尾。publicStringBufferinsert(intoffset,Stringstr)將字符串str插入到此字符序列中,offset表示插入位置。StringBuilder22StringBuilder類是在Java5.0中被提出的,它和StringBuffer之間的最大不同在于StringBuilder的方法是非線程安全的,而StringBuffer是線程安全的對(duì)于我們初學(xué)者而言,非線程安全意味著速度更快,因此在目前階段建議使用StringBuilder類;等以后大家學(xué)習(xí)了高并發(fā)相關(guān)內(nèi)容以后,再根據(jù)情況考慮使用StringBuffer。StringBuilder23StringBuffer是一個(gè)內(nèi)容可變的字符序列,或者說(shuō)它是一個(gè)內(nèi)容可變的字符串類型。當(dāng)使用StringBufferstrB1=newStringBuffer("柳海龍");語(yǔ)句創(chuàng)建StringBuffer對(duì)象時(shí),內(nèi)存結(jié)構(gòu)示意圖如圖所示。StringBuilder24當(dāng)使用strB1.append("工程師")方法時(shí),將之前創(chuàng)建的StringBuffer對(duì)象的內(nèi)容“柳海龍”修改成“柳海龍工程師”,內(nèi)存結(jié)構(gòu)示意圖如圖所示Date類25JDK8.0以前的Date類用于定義當(dāng)前的日期和時(shí)間,提供了以下常用方法Date(longmillisec)帶一個(gè)參數(shù)的Date構(gòu)造方法,該參數(shù)是從1970年1月1日零點(diǎn)起的毫秒數(shù)。longgetTime()返回自1970年1月1日零點(diǎn)以來(lái),此Date對(duì)象經(jīng)過的毫秒數(shù)。booleanafter(Datedate)判斷當(dāng)前對(duì)象是否在參數(shù)date指定的日期之后。如果是返回true,否則返回false。booleanbefore(Datedate)判斷當(dāng)前對(duì)象是否在參數(shù)date指定的日期之前。如果是返回true,否則返回false。Date類26在JDK8.0提供的新日期API中,所有的類都是不可變的,這就對(duì)高并發(fā)編程提供了友好支持。并且新的API將“時(shí)間”的概念更加精細(xì)化,提供了日期(Date)、時(shí)間(Time)、日期時(shí)間(DateTime)、時(shí)間戳(unixtimestamp)以及時(shí)區(qū)等細(xì)化的時(shí)間類DK8.0新增的日期API都在java.time包下,其中常見的API如下表所示SimpleDateFormat類27在SimpleDateFormat中,是通過構(gòu)造方法指定Date的輸出格式的,并且在設(shè)置這些格式時(shí)需要使用時(shí)間通配符,常見的通配符如下表所示例如yyyy-MM-ddHH:mm:ss就代表了“4位數(shù)年-2位數(shù)月-2位數(shù)日2位數(shù)時(shí):2位數(shù)分:2位數(shù)秒”的日期顯示格式其他類28除了Date和SimpleDateFormat以外,JDK還提供了非常豐富的其他工具類例如,Calendar類為特定時(shí)間與日歷字段(YEAR、MONTH、DAY_OF_MONTH、HOUR等)之間的轉(zhuǎn)換,以及操作日歷字段提供了一些方法。而Math類可以方便的進(jìn)行一些數(shù)學(xué)運(yùn)算。Calendar、Math以及其它工具類的具體使用,大家可以查閱JavaAPI文檔。筆試題29下列String字符串類的()方法實(shí)現(xiàn)了“將一個(gè)字符串按照指定的分隔符分隔,返回分隔后的字符串?dāng)?shù)組”的功能。Asubstring(...)Bsplit(...)CvalueOf(...)Dreplace(...)筆試題30給定如下Java代碼,編譯運(yùn)行后,輸出的結(jié)果將是()?publicclassTest{publicstaticvoidmain(Stringargs[]){Strings1=newString("Test");Strings2=newString("Test");if(s1==s2)System.out.println("Same");if(s1.equals(s2))System.out.println("Equals");}}ASameBEqualsCSameEqualsD什么都不輸出筆試題31StringBuilder和StringBuffer的區(qū)別,下面說(shuō)法錯(cuò)誤的是?()AStringBuffer是線程安全的BStringBuilder是非線程安全的CStringBuffer對(duì)String類型進(jìn)行改變的時(shí)候其實(shí)都等同于生成了一個(gè)新的String對(duì)象,然后將指針指向新的String對(duì)象D字符串拼接效率比較String<StringBuffer<StringBuilder筆試題32編寫程序,實(shí)現(xiàn)以下功能:計(jì)算某個(gè)字符串中,某個(gè)字符出現(xiàn)的次數(shù)Java程序設(shè)計(jì)基礎(chǔ)類和對(duì)象類和對(duì)象串主要內(nèi)容346.1面向?qū)ο螅ㄖ攸c(diǎn))6.2Java中的類(重點(diǎn))6.3構(gòu)造方法(重點(diǎn))6.4對(duì)象的初始化過程(難點(diǎn))6.5重載(重點(diǎn))教學(xué)目標(biāo)35能理解類和對(duì)象的概念能準(zhǔn)確區(qū)分類和對(duì)象的不同及聯(lián)系能正確使用類和對(duì)象開發(fā)程序能理解封裝的概念能準(zhǔn)確使用封裝增加程序的安全性能理解構(gòu)造方法的概念能正確使用this區(qū)分重名變量教學(xué)目標(biāo)36能正確使用this調(diào)用同類中的其他構(gòu)造方法能理解對(duì)象初始化時(shí)內(nèi)存的演變過程能理解重載的概念能正確使用重載提高程序的復(fù)用性能正確使用類和對(duì)象解決實(shí)際問題面向?qū)ο缶幊?7面向?qū)ο螅嫦驅(qū)ο缶幊痰暮?jiǎn)稱,ObjectOrientedProgramming,OOP)是一種對(duì)現(xiàn)實(shí)世界理解和抽象的方法,是計(jì)算機(jī)編程技術(shù)發(fā)展到一定階段后的產(chǎn)物通過面向?qū)ο蟮姆绞?,將現(xiàn)實(shí)世界的事物抽象成對(duì)象,將現(xiàn)實(shí)世界中的關(guān)系抽象成關(guān)聯(lián)、繼承、實(shí)現(xiàn)、依賴等關(guān)系,從而幫助人們實(shí)現(xiàn)對(duì)現(xiàn)實(shí)世界的抽象與建模通過面向?qū)ο蟮姆椒ǎ谌藗兝斫?,更利于?duì)復(fù)雜系統(tǒng)進(jìn)行分析、設(shè)計(jì)與開發(fā)。同時(shí),面向?qū)ο笠材苡行岣呔幊痰男?,通過封裝技術(shù)和消息機(jī)制可以像搭積木一樣快速開發(fā)出一個(gè)全新的系統(tǒng)五子棋38要編寫一個(gè)五子棋的游戲,用面向?qū)ο蟮脑O(shè)計(jì)思路,其分析步驟如下棋盤部分:負(fù)責(zé)繪制基本畫面以及黑棋、白棋走完后的畫面黑棋、白棋:除了顏色不一樣外,其行為是一樣的規(guī)則部分:負(fù)責(zé)判定輸贏和犯規(guī)思考:如果用面向過程的設(shè)計(jì)思路,應(yīng)該如何分析?五子棋39總的來(lái)說(shuō):OOP以對(duì)象來(lái)劃分系統(tǒng)OOP將屬性和行為放入對(duì)象OOP通過呼叫對(duì)象使其執(zhí)行行為來(lái)完成功能OOP使程序易于維護(hù)和擴(kuò)展類與對(duì)象的概念40在編程世界中,萬(wàn)物皆對(duì)象。例如,一輛具體的汽車、一間具體的房子、一張具體的支票、一個(gè)具體的桌子也是對(duì)象,甚至一項(xiàng)具體的計(jì)劃、一個(gè)具體的思想都是對(duì)象。在Java面向?qū)ο缶幊讨?,將這些對(duì)象的屬性仍然稱為屬性,將對(duì)象具有的行為稱為方法(Mathod)。例如,教師具有姓名、性別、年齡、學(xué)歷這些屬性,小轎車具有品牌、顏色、價(jià)格等屬性,這些屬性具體的值稱為屬性值。教師具有講課、批改作業(yè)等行為,小轎車具有行駛、停止、喇叭響等行為,這些行為稱為方法??梢姡椒ㄊ且环N動(dòng)態(tài)的行為,而屬性是一種靜態(tài)的特征屬性通常是名詞,行為或方法通常是動(dòng)詞什么是類?類是對(duì)具有相同屬性和相同行為的對(duì)象的抽象。類的基本語(yǔ)法41類定義的語(yǔ)法形式publicclass類名{//定義類屬性屬性1類型:屬性1名;屬性2類型:屬性2名;…//定義方法方法1定義方法2定義…}類的主要內(nèi)容分兩部分,第一部分是類的屬性定義,在前面的課程中學(xué)習(xí)過,在類內(nèi)部、方法外部定義的變量稱為成員變量,也可以稱為成員屬性,或簡(jiǎn)稱為“屬性”。第二部分是類的方法定義,通過方法的定義,描述類(對(duì)象)具有的動(dòng)態(tài)行為,這些方法也可以稱為成員方法,或簡(jiǎn)稱為“方法”。類的基本語(yǔ)法42定義好一個(gè)類后,就可以根據(jù)這個(gè)類創(chuàng)建(實(shí)例化)對(duì)象了。類就相當(dāng)于一個(gè)模板,可以創(chuàng)建多個(gè)對(duì)象。創(chuàng)建對(duì)象的語(yǔ)法形式如下。類名對(duì)象名=new類名();之后再通過.操作符來(lái)引用對(duì)象的屬性和方法,具體的語(yǔ)法形式如下。對(duì)象名.屬性;對(duì)象名.方法();初始封裝43封裝的目的是簡(jiǎn)化編程和增強(qiáng)安全性。簡(jiǎn)化編程是指,封裝可以讓使用者不必了解具體類的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),而只是要通過提供給外部訪問的方法來(lái)訪問類中的屬性和方法。例如JavaAPI中的Arrays.sort()方法,該方法可以用于給數(shù)組進(jìn)行排序操作,開發(fā)者只需要將待排序的數(shù)組名放到Arrays.sort()方法的參數(shù)中,該方法就會(huì)自動(dòng)的將數(shù)組排好序。增強(qiáng)安全性是指,封裝可以使某個(gè)屬性只能被當(dāng)前類使用,從而避免被其他類或?qū)ο筮M(jìn)行誤操作。例如在Student.java的程序中,Student的stuAge屬性是public的形式體現(xiàn)的,但這樣做實(shí)際存在著安全隱患:TestStudent類(或在訪問修飾符可見范圍內(nèi)的其他類)完全可以隨意的對(duì)stuAge進(jìn)行修改,封裝如何保證數(shù)據(jù)的安全性44封裝1用private禁止其他類直接訪問屬性;2給1中的屬性新增兩個(gè)public修飾的setter和getter方法,供其他類安全的訪問。setter方法用于給屬性賦值,而getter訪問用于獲取屬性的值。并且一般而言,setter方法的名字通常是set+屬性名,getter方法的名字通常是get+屬性名。封裝如何保證數(shù)據(jù)的安全性45示例publicclassStudent{privateintstuAge;publicintgetStuAge(){returnstuAge;}publicvoidsetStuAge(intage){if(age>0&&age<110)stuAge=age;elseage=0;}}構(gòu)造方法的基本語(yǔ)法46構(gòu)造方法(也稱為構(gòu)造函數(shù))是一種特殊的方法,它具有以下特點(diǎn)。構(gòu)造方法的方法名必須與類名相同構(gòu)造方法沒有返回類型,在方法名前不聲明返回類型(包括void)構(gòu)造方法的語(yǔ)法形式如下[訪問修飾符]類名([參數(shù)列表]);this關(guān)鍵字47this是Java的一個(gè)關(guān)鍵字,它表示“指向當(dāng)前對(duì)象的引用(簡(jiǎn)稱為‘當(dāng)前對(duì)象’)”在實(shí)際開發(fā)時(shí),this通常用于以下兩個(gè)場(chǎng)景。區(qū)分成員變量和局部變量,避免命名的煩惱。調(diào)用其他構(gòu)造方法。使用this關(guān)鍵字區(qū)分成員變量48可以通過this來(lái)區(qū)分名稱相同的不同變量,如下所示。privateintage;...publicvoidsetAge(intage){...this.age=age;}在this.age=age;這句代碼中,因?yàn)閠his代表著當(dāng)前對(duì)象,因此this.age就代表了當(dāng)前對(duì)象的age屬性;而age沒有this修飾,就會(huì)根據(jù)變量的作用域,默認(rèn)為方法參數(shù)中的age使用this關(guān)鍵字調(diào)用其他構(gòu)造方法49可以使用this調(diào)用類中的其他構(gòu)造方法,但這種this()語(yǔ)句必須寫在構(gòu)造方法的一行publicStudent(){this("WangYun");}publicStudent(Stringname){this(name,23);}publicStudent(Stringname,intage){...}需要注意的是,所有的構(gòu)造方法之間不能循環(huán)調(diào)用,否則會(huì)出現(xiàn)類似“死循環(huán)”的現(xiàn)象。例如以上代碼,如果在最后一個(gè)構(gòu)造方法的第一行也加上this(),那么三個(gè)構(gòu)造方法就會(huì)無(wú)限制的彼此調(diào)用。對(duì)象初始化簡(jiǎn)介50對(duì)象的初始化,實(shí)際就是先在堆內(nèi)存中申請(qǐng)一塊用于存放對(duì)象屬性值的空間,然后再給這些屬性值賦上默認(rèn)值、程序員期望的數(shù)據(jù)或者用戶指定的數(shù)據(jù)。當(dāng)堆內(nèi)存中的這塊空間有了值以后,再在??臻g中申請(qǐng)一塊空間并存放引用變量,然后用棧中的引用變量指向堆中的對(duì)象,最終就可以通過棧中的引用變量訪問或者修改堆中的對(duì)象了對(duì)象初始化過程中內(nèi)存的演變51閱讀以下代碼publicclassStudent{privateStringname="";privateintage=-1;privateintsex=-1;privateintgrade=-1;//使用初始化塊初始化{System.out.println("使用初始化塊初始化");="雷靜";this.age=22;this.sex=2;this.grade=4;}對(duì)象初始化過程中內(nèi)存的演變52//無(wú)參構(gòu)造方法publicStudent(){System.out.println("使用無(wú)參構(gòu)造函數(shù)初始化");}//構(gòu)造方法,用戶初始化對(duì)象的成員變量publicStudent(Stringname,intage,intsex,intgrade){System.out.println("使用有參構(gòu)造函數(shù)初始化");=name;this.age=age;this.sex=sex;this.grade=grade;}//省略了Student類中的其他方法}對(duì)象初始化過程中內(nèi)存的演變53publicclassTestStudent{publicstaticvoidmain(String[]args){Studenttemp=newStudent();System.out.println(temp.getName()+"正在讀大學(xué)"+temp.getGrade()+"年級(jí)");//構(gòu)造方法初始化成員變量在初始化塊執(zhí)行之后StudentwangYun=newStudent("王云",22,1,4);System.out.println(wangYun.getName()+"正在讀大學(xué)"+wangYun.getGrade()+"年級(jí)");}}對(duì)象初始化過程中內(nèi)存的演變54以上代碼,在對(duì)象初始化時(shí)的內(nèi)存演變過程如下。(1)“Studenttemp=newStudent();”執(zhí)行時(shí),首先需要在堆內(nèi)存中申請(qǐng)空間,用于存放對(duì)象的實(shí)例,這片空間上成員變量的值全部為默認(rèn)值:name的值是null、age的值是0……對(duì)象初始化過程中內(nèi)存的演變55(2)緊接著,執(zhí)行聲明初始化(由設(shè)計(jì)該類的開發(fā)者指定),例如在Student類中“privateintage=-1;”代表程序員希望age屬性用值-1覆蓋默認(rèn)值對(duì)象初始化過程中內(nèi)存的演變56(3)初始化塊初始化。初始化塊就是在類的下一級(jí)(與成員變量和成員方法同級(jí))用一對(duì)大括號(hào)括起來(lái)的代碼塊,語(yǔ)法形式如下:{代碼塊}對(duì)象初始化過程中內(nèi)存的演變57初始化塊可以用來(lái)覆蓋類的成員變量的值,初始化塊的執(zhí)行時(shí)機(jī)是發(fā)生在“聲明初始化”之后,在“構(gòu)造器初始化”之前。例如,程序清單6.12中的如下初始化代碼,就用于給成員變量再次賦值{="雷靜";this.age=22;this.sex=2;this.grade=4;}對(duì)象初始化過程中內(nèi)存的演變58(4)構(gòu)造器初始化,例如“Studenttemp=newStudent("王云",22,1,4);”,在默認(rèn)初始化,聲明初始化,初始化塊之后,再此用構(gòu)造器覆蓋各個(gè)屬性的值重載59在同一個(gè)類中,可以有兩個(gè)或兩個(gè)以上的方法具有相同的方法名,但它們的參數(shù)列表不同。這種形式被稱為重載(overload)。所謂參數(shù)列表不同包括以下三種情形。參數(shù)的數(shù)量不同。參數(shù)的類型不同。參數(shù)的順序不同。重載60必須注意的是,僅返回值不同不能視為方法重載,還會(huì)得到一個(gè)語(yǔ)法錯(cuò)誤。而且重載的方法之間只是“碰巧”名稱相同罷了,不具備連帶效應(yīng)。既然方法名稱相同,在使用相同的名稱調(diào)用方法時(shí),編譯器怎么確定調(diào)用哪個(gè)方法呢?這就要靠傳入?yún)?shù)的不同確定具體調(diào)用哪個(gè)方法。一個(gè)類的多個(gè)構(gòu)造方法被視為重載,因?yàn)槎鄠€(gè)構(gòu)造方法的方法名相同,而參數(shù)列表不同,符合重載的定義。筆試題61下面對(duì)于類和對(duì)象的描敘錯(cuò)誤的是()?A類可以產(chǎn)生對(duì)象B對(duì)象可以抽象出類C類是抽象的,對(duì)象是具體的D對(duì)類細(xì)分后的產(chǎn)物就是對(duì)象筆試題62下面對(duì)于構(gòu)造方法的描敘正確的是()?A類中必須顯式定義構(gòu)造方法B構(gòu)造方法的返回類型是voidC構(gòu)造方法名和類名完全一致,并且不能帶任何參數(shù)D一個(gè)類中可以定義多個(gè)構(gòu)造方法筆試題63在某個(gè)類中存在一個(gè)方法:void?getSort(int?x),以下能作為這個(gè)方法的重載聲明的是()?ApublicgetSort(floatx)BintgetSort(inty)CdoublegetSort(intx,inty)Dvoidget(intx,inty)筆試題64重寫與重載的關(guān)系是()?A重寫只有出現(xiàn)在父類與子類之間,而重載可以出現(xiàn)在同一個(gè)類中B重寫方法可以有不同的方法名,而重載方法必須是相同的方法名Cfinal修飾的方法可以被重寫,但不能被重載D重寫與重載是同一個(gè)概念的不同描述Java程序設(shè)計(jì)基礎(chǔ)包和訪問控制包和訪問控制主要內(nèi)容667.1Java包概述7.2引用包(重點(diǎn))7.3訪問控制(重點(diǎn))7.4static關(guān)鍵字教學(xué)目標(biāo)67能理解包概念能正確使用包避免類重名問題能正確使用包對(duì)多個(gè)類進(jìn)行歸類能描述包的命名規(guī)則能理解引用包的作用和場(chǎng)景能正確的在程序中打包并導(dǎo)入包能區(qū)分四種訪問修飾符能準(zhǔn)確使用四種訪問修飾符能理解static關(guān)鍵字的作用能正確使用static關(guān)鍵字修飾類的成員能理解Java靜態(tài)塊能正確使用初始化塊和靜態(tài)初始化塊初始化程序能理解并編寫單例設(shè)計(jì)模式包的簡(jiǎn)介68計(jì)算機(jī)中存放了若干類型的文檔,為了管理方便,操作系統(tǒng)采用了樹形結(jié)構(gòu)的文件夾形式存放這些文檔,并對(duì)文檔進(jìn)行管理。類似的,為了更好地組織類,Java提供了包機(jī)制。包是類的容器,用于分隔類名空間。如果沒有指定包名,所有的類都屬于一個(gè)默認(rèn)的無(wú)名包。Java中將實(shí)現(xiàn)相關(guān)功能的類組織到一個(gè)包中。例如,Java中通用的工具類,一般都放在java.util包中??偟膩?lái)說(shuō),包有以下三個(gè)方面的作用:提供了類似于操作系統(tǒng)樹形文件夾的組織形式,能分門別類地存儲(chǔ)、管理類,易于查找并使用類。解決了同名類的命名沖突問題。包允許在更廣的范圍內(nèi)保護(hù)類、屬性和方法。包的語(yǔ)法69程序員可以使用package關(guān)鍵字指明源文件中的類屬于哪個(gè)具體的包,包的語(yǔ)法形式如下。 packagepkg1[.pkg2[.pkg3…]];程序中如果有package語(yǔ)句,該語(yǔ)句一定是源文件中的第一條可執(zhí)行語(yǔ)句,它的前面只能有注釋或空行。一個(gè)文件中最多只能有一條package語(yǔ)句,即只能把一個(gè)類放在一個(gè)包中。包的名字應(yīng)該有層次關(guān)系,各層之間以.分隔。包的命名規(guī)則70命名規(guī)則通常包名全部用小寫字母,這與類名以大寫字母開頭且各單詞的首字母亦大寫的命名約定有所不同。關(guān)于包的命名,現(xiàn)在使用最多的規(guī)則是使用翻轉(zhuǎn)的internet域名(不含www、ftp等訪問協(xié)議)。例如abc公司的域名為,該公司開發(fā)部門正開發(fā)一個(gè)名為fly的項(xiàng)目,在這個(gè)項(xiàng)目中有一個(gè)工具類的包,則這個(gè)工具包的包名可以為:com.abc.fly.tools。JDK類庫(kù)里的包71java.lang:lang是language的簡(jiǎn)寫,這個(gè)包提供Java語(yǔ)言的基礎(chǔ)類,例如String、Math、Integer、System和Thread等。java.util:util是utility的簡(jiǎn)寫,組織了Java的工具類,包含集合、事件模型、日期和時(shí)間設(shè)置、國(guó)際化和各種實(shí)用工具類。java.io:io是input和output的合并簡(jiǎn)寫,指輸入和輸出,組織了數(shù)據(jù)流、序列化和文件系統(tǒng)相關(guān)的類。:net即網(wǎng)絡(luò),這個(gè)包組織了為實(shí)現(xiàn)網(wǎng)絡(luò)應(yīng)用程序而提供的類。java.awt:抽象窗口工具集(AbstractWindowToolkit),包含用于創(chuàng)建用戶界面和繪制圖形圖像的類。引用包的作用72思考:如果兩個(gè)Java類不在同一個(gè)包中,這兩個(gè)類之間如何相互引用

引用包才能解決上述問題引用不同包中類的兩種方式73一種非常直觀的方法就是使用完整類名引用類,即包名+類名(也稱為類的全限定名)。另一種是導(dǎo)入包的形式。使用類的全限定名的方法雖然直觀,但書寫的內(nèi)容多,且當(dāng)使用的類比較多時(shí),編輯和閱讀都非常困難,因此并不推薦。接下來(lái)學(xué)習(xí)的是采用導(dǎo)入包的形式引用類,導(dǎo)入包的語(yǔ)法形式如下。

import包名.類名;這里的包名、類名既可以是JDK提供的包和類的名稱,也可以是用戶自定義的包名和類名。如果要使用一個(gè)包中的多個(gè)類,可以使用import包名.*;的形式導(dǎo)入這個(gè)包中所有的類。不過,包的導(dǎo)入只能導(dǎo)入當(dāng)前目錄中的類,而不能導(dǎo)入其子目錄中的類。例如在導(dǎo)入java.util.*時(shí),只會(huì)導(dǎo)入java.util包中的所有類,但不能導(dǎo)入java.util.function包中的類。另外,import語(yǔ)句需要放在package語(yǔ)句后,在類定義之前。同時(shí)導(dǎo)入多個(gè)包74如果一個(gè)程序同時(shí)存在Date類和Scanner類,就可以通過兩條import語(yǔ)句分別導(dǎo)入二者,如下所示。importjava.util.Date;//導(dǎo)入java.util包中的Date類importjava.util.Scanner;//導(dǎo)入java.util包中的Scanner類java還提供了一種批量導(dǎo)入的方式:如果要導(dǎo)入的多個(gè)類存在于同一個(gè)包中,那么可以使用通配符*代表包中的所有類。例如可以使用importjava.util.*代表導(dǎo)入了java.util包中的所有類,如下所示。importjava.util.*;

訪問權(quán)限修飾符75有些類并不希望被其他類使用,有些屬性和方法需要對(duì)外界不可見或僅在有限的范圍內(nèi)可見。Java語(yǔ)言中的訪問權(quán)限修飾符有4種,但卻只有3個(gè)關(guān)鍵字。因?yàn)椴粚懺L問權(quán)限修飾符時(shí),在Java中被稱為默認(rèn)權(quán)限(包權(quán)限),本課程中以default代替。其他3個(gè)訪問權(quán)限修飾符分別為private、protected和public。如何實(shí)現(xiàn)對(duì)類的訪問控制76對(duì)于類而言,目前能使用的訪問權(quán)限修飾符只有public和default如果使用public修飾某個(gè)類,則表示該類在任何地方都能被訪問,如果不寫訪問權(quán)限修飾符,則該類只能在本包中使用。4種類成員訪問權(quán)限修飾符77對(duì)于類的成員(屬性和方法)而言,4種訪問權(quán)限修飾符都可以使用。下面按照權(quán)限從小到大的順序(即private<default<protected<public)對(duì)四種訪問權(quán)限修飾符分別進(jìn)行介紹。私有權(quán)限privateprivate可以修飾屬性、構(gòu)造方法、普通方法。被private修飾的類成員只能在定義它們的類中使用,在其他類中都不能訪問。默認(rèn)權(quán)限default不寫任何權(quán)限關(guān)鍵字就代表使用默認(rèn)權(quán)限,屬性、構(gòu)造方法、普通方法都能使用默認(rèn)權(quán)限。默認(rèn)權(quán)限也稱為同包權(quán)限。同包權(quán)限的元素只能在定義它們的類中以及同包的類中被調(diào)用。4種類成員訪問權(quán)限修飾符78受保護(hù)權(quán)限protectedprotected可修飾屬性、構(gòu)造方法、普通方法,能在定義它們的類中以及同包的類中調(diào)用被protected修飾的成員。如果有不同包中的類想調(diào)用它們,那么這個(gè)類必須是這些成員所屬類的子類。關(guān)于子類及相關(guān)概念,將會(huì)在后續(xù)講解繼承的時(shí)候詳細(xì)介紹。公共權(quán)限publicpublic可以修飾屬性、構(gòu)造方法和普通方法。被public修飾的成員,可以在任何一個(gè)類中被調(diào)用,是權(quán)限最大的訪問權(quán)限修飾符。4種類成員訪問權(quán)限修飾符79

Static關(guān)鍵字的作用80對(duì)象的成員變量有兩種級(jí)別的使用范圍:對(duì)象級(jí)別和類級(jí)別?!皩?duì)象名.變量名”的形式訪問,實(shí)際就是對(duì)象級(jí)別的訪問形式。對(duì)象級(jí)別的成員變量只能在當(dāng)前對(duì)象的范圍內(nèi)使用。在類成員的聲明前,加上static(靜態(tài)的)關(guān)鍵字,就能創(chuàng)建出類級(jí)別的成員變量。聲明為static的變量稱為靜態(tài)變量或類變量。可以直接通過類名引用靜態(tài)變量,也可以通過實(shí)例名來(lái)引用靜態(tài)變量,但推薦采用前者,因?yàn)椴捎煤笳呷菀谆煜o態(tài)變量和實(shí)例變量。除了修飾變量以外,聲明為static的方法稱為靜態(tài)方法或類方法,最常見的例子是main方法。和靜態(tài)變量一樣,靜態(tài)方法也可以被類名直接引用。靜態(tài)方法可以直接調(diào)用靜態(tài)方法,訪問靜態(tài)變量,但是不能直接訪問實(shí)例變量和實(shí)例方法。靜態(tài)方法中不能使用this關(guān)鍵字,因?yàn)殪o態(tài)方法不屬于任何一個(gè)實(shí)例。靜態(tài)方法不能操作實(shí)例變量81靜態(tài)方法可以操作靜態(tài)變量,不能操作實(shí)例變量,通過下面的例子看出(編譯時(shí)報(bào)錯(cuò))。publicclassStudent{publicintavgAge=22;//實(shí)例變量,存放平均年齡publicstaticvoidshowAvgAge(){//靜態(tài)方法調(diào)用實(shí)例變量—編譯出錯(cuò)System.out.println("靜態(tài)方法輸出所在班平均年齡為:"+avgAge);}}Java靜態(tài)塊82靜態(tài)塊的語(yǔ)法形式如下。static{語(yǔ)句塊}Java類首次裝入JVM時(shí),會(huì)對(duì)靜態(tài)成員或靜態(tài)塊進(jìn)行一次初始化,注意此時(shí)還沒有產(chǎn)生對(duì)象。因此,靜態(tài)成員和靜態(tài)塊都是和類綁定的,會(huì)在類加載時(shí)就進(jìn)行初始化操作。當(dāng)類加載完畢后,才能實(shí)例化出對(duì)象,并在對(duì)象產(chǎn)生的同時(shí)對(duì)實(shí)例成員進(jìn)行初始化。因此,實(shí)例成員是和對(duì)象綁定的,會(huì)在實(shí)例化對(duì)象時(shí)一并進(jìn)行初始化。單例模式83單例模式是指:無(wú)論創(chuàng)建了多少個(gè)引用,在堆中僅僅只有一個(gè)實(shí)例對(duì)象,如圖所示。單例模式84實(shí)現(xiàn)單例模式的核心是思路是將構(gòu)造方法私有化,即使用private修飾構(gòu)造方法,然后利用static成員變量的“一次性”,如下所示。publicclassSingleton{privateSingleton(){}}筆試題85下面那種權(quán)限是同一包可以訪問,不同包的子類可以訪問,不同包的非子類不可以訪問()?AprivateBdefault(默認(rèn))CprotectedDpublic筆試題86下面對(duì)static的描述錯(cuò)誤的是()?A靜態(tài)修飾的成員變量和成員方法隨著類的加載而加載B靜態(tài)修飾的成員方法可以訪問非靜態(tài)成員變量C靜態(tài)修飾的成員可以被整個(gè)類對(duì)象所共享D靜態(tài)修飾的成員變量和成員方法隨著類的消失而消失筆試題87下面對(duì)單例設(shè)計(jì)模式的描述錯(cuò)誤的是()?A在單例模式中,不論創(chuàng)建多少個(gè)引用,都只有一份堆對(duì)象B單例模式可以通過構(gòu)造方法私有化實(shí)現(xiàn)C單例模式可以減少程序中堆對(duì)象的個(gè)數(shù)D單例模式是工廠模式的另一種別名Java程序設(shè)計(jì)基礎(chǔ)面向?qū)ο蠡咎卣髅嫦驅(qū)ο蠡咎卣髦饕獌?nèi)容898.1抽象和封裝(重點(diǎn))8.2繼承(重點(diǎn))8.3多態(tài)(重點(diǎn)、難點(diǎn))教學(xué)目標(biāo)90能理解抽象的概念能正確使用抽象的思想設(shè)計(jì)程序能理解繼承的概念能正確描述無(wú)法使用繼承的兩種情況能描述final關(guān)鍵字的作用能正確區(qū)分super與this關(guān)鍵字的作用能理解多態(tài)的概念能正確使用多態(tài)簡(jiǎn)化程序能理解面向基類的編程思想能理解向上轉(zhuǎn)型和向下轉(zhuǎn)型的概念能正確區(qū)分向上轉(zhuǎn)型和向下轉(zhuǎn)型什么是抽象91有些資料把抽象和封裝、繼承、多態(tài)一起并稱為面向?qū)ο蟮乃拇筇卣鳎ǖ髁鞯恼f(shuō)法,仍然是三大特征)。面向?qū)ο笤O(shè)計(jì)首先要做的就是抽象,也就是根據(jù)用戶的業(yè)務(wù)需求抽象出類,并關(guān)注這些類的屬性和方法,將現(xiàn)實(shí)世界中的對(duì)象抽象成程序設(shè)計(jì)中的類。程序員開發(fā)出來(lái)的軟件是需要滿足用戶需求的,所以程序員做分析和設(shè)計(jì)的依據(jù)是用戶需求,這通常就是軟件開發(fā)前期形成的“需求規(guī)格說(shuō)明書”。面向?qū)ο笤O(shè)計(jì)時(shí),首先要閱讀用戶需求,找出需求中名詞部分用來(lái)確定類和擁有靜態(tài)特征的屬性,找出動(dòng)詞部分確定動(dòng)態(tài)行為的方法。“租車系統(tǒng)”需求抽象分析92分析一個(gè)“租車系統(tǒng)”的部分需求。在控制臺(tái)輸出“請(qǐng)選擇要租車的類型:(1代表轎車,2代表卡車)”,等待用戶輸入。如果用戶選擇的是轎車,則在控制臺(tái)輸出“請(qǐng)選擇轎車品牌:(1代表紅旗,2代表長(zhǎng)城)”,等待用戶輸入。如果用戶選擇的是卡車,則在控制臺(tái)輸出“請(qǐng)選擇卡車噸位:(1代表5噸,2代表10噸)”,等待用戶輸入。在控制臺(tái)輸出“請(qǐng)給所租的車起名:”,等待用戶輸入車名。所租的車油量默認(rèn)值為20升,車輛損耗度為0(表示剛保養(yǎng)完的車,無(wú)損耗)。具有顯示所租車輛信息功能,顯示的信息包括車名、品牌/噸位、油量和車損度?!白廛囅到y(tǒng)”需求抽象分析93首先我們進(jìn)行抽象,發(fā)現(xiàn)需求里的類并定義類的屬性和方法:發(fā)現(xiàn)名詞。通過閱讀需求,發(fā)現(xiàn)需求中有類型、轎車、卡車、品牌、紅旗、長(zhǎng)城等名詞。確定類和屬性。通過分析,車名、油量、車損度、品牌這些名詞依附于轎車這個(gè)名詞,車名、油量、車損度、噸位依附于卡車這個(gè)名詞,所以可以將轎車、卡車抽象成類,依附于這些類的名詞抽象成屬性。確定方法。通過分析需求的動(dòng)詞,發(fā)現(xiàn)顯示車輛信息是轎車和卡車的行為,所以可以將這個(gè)行為抽象成類的方法。同樣地,不是所有依附于類名詞的動(dòng)詞都需要抽象成類的方法,只有需要參與業(yè)務(wù)處理的動(dòng)詞才能確定成方法?!白廛囅到y(tǒng)”需求抽象分析94據(jù)對(duì)轎車和卡車的抽象,可以得到如圖所示的結(jié)果封裝“租車系統(tǒng)”的轎車類和卡車類95把所有的屬性都設(shè)置為私有屬性,每個(gè)私有屬性都提供getter和setter公有的方法,封裝后的類圖如下圖所示封裝“租車系統(tǒng)”的轎車類和卡車類96上述封裝過于簡(jiǎn)單,沒有考慮需求,接下來(lái)進(jìn)一步閱讀需求,可以發(fā)現(xiàn)以下幾點(diǎn)。租車時(shí)可以指定車的類型和品牌(或噸位),之后不允許修改。油量和車損度租車時(shí)取默認(rèn)值,只有通過車的加油和行駛的行為改變其油量和車損度值,不允許修改。根據(jù)需求,應(yīng)對(duì)轎車類和卡車類做如下修改。由于要求了車的屬性值不允許修改,因此去掉所有的setter方法,但保留所有的getter方法。提供addOil()、drive()這兩個(gè)公有的方法,實(shí)現(xiàn)車的加油和行駛的行為。至少需要提供一個(gè)構(gòu)造方法,實(shí)現(xiàn)對(duì)類型和品牌(或噸位)的初始化。封裝“租車系統(tǒng)”的轎車類和卡車類97調(diào)整后的類圖如圖所示抽象和封裝的具體體現(xiàn)98抽象,實(shí)際上是一個(gè)分析的過程,是根據(jù)需求的表述歸納實(shí)體的類型、屬性和行為,其產(chǎn)出物是類圖。類圖勾勒了實(shí)體應(yīng)該具備哪些屬性和行為,但未涉及細(xì)節(jié)。封裝,實(shí)則就是將抽象得到的模型轉(zhuǎn)變?yōu)榫唧w實(shí)現(xiàn)。它的要點(diǎn)是,盡可能對(duì)外隱藏細(xì)節(jié),Java中的手段就是使用private,所以在前面案例中所有的屬性都是private。抽象,是歸納提煉;封裝則是在實(shí)現(xiàn)中依據(jù)業(yè)務(wù)需求盡量隱藏細(xì)節(jié)。為什么要使用繼承99用繼承可以大大減少冗余代碼,提高代碼的復(fù)用性。我們之間添加的Car.java和Truck.java中的代碼,可以發(fā)現(xiàn)現(xiàn)有代碼存在著以下的不足Car類和Truck類中的代碼大量重復(fù):例如二者都存在name、oil、loss屬性,相應(yīng)的getter方法,以及addOil()、drive()等方法。對(duì)于整體結(jié)構(gòu)相似的Car類和Truck類,如果要修改其中的一個(gè)類的方法,另外一個(gè)類的方法要不要修改呢?例如,如果要將Car類中的addOil()方法改為fuelUp()方法,那么Truck類中是否也需要做相應(yīng)的修改呢?顯然,目前這種做法給后期的代碼維護(hù)帶來(lái)了麻煩。為什么要使用繼承100上述的問題可以使用繼承解決。繼承可以使得子類沿用父類的成員(屬性和方法)。當(dāng)多個(gè)子類具有相同的成員時(shí),就可以考慮將這些成員提取出來(lái),放到父類中,然后再用子類去繼承這個(gè)父類,也就是將一些相同的成員提取到了更高的層次中。繼承的關(guān)鍵字是extends,語(yǔ)法形式如下。classAextendsB{類定義部分}以上表示A類繼承B類,B類稱為父類、超類或基類;A類稱為子類、衍生類或?qū)С鲱?。無(wú)法繼承的兩種特殊情況101以下是兩種特殊的情況不能使用繼承子類無(wú)法繼承父類的構(gòu)造方法子類不能繼承父類中不符合訪問權(quán)限的成員方法重寫102有的時(shí)候,父類繼承而來(lái)的方法不能滿足子類的需要,此時(shí)就可以在子類中對(duì)父類的同名方法進(jìn)行覆蓋,這就是重寫。final關(guān)鍵字103重寫在語(yǔ)法上需要滿足如下條件。重寫方法與被重寫方法同名,參數(shù)列表也必須相同。重寫方法的返回值類型必須和被重寫方法的返回值類型相同或是其子類。重寫方法不能縮小被重寫方法的訪問權(quán)限。同時(shí)調(diào)用父類子類104以下是借助于super()同時(shí)調(diào)用父類及子類的示例代碼publicclassCarextendsVehicle{privateStringbrand="紅旗";publicCar(Stringname,Stringbrand){super(name);//使用super關(guān)鍵字,調(diào)用父類的構(gòu)造方法this.brand=brand;}...}父類中沒有無(wú)參構(gòu)造器的兩種常見處理方式105在子類構(gòu)造方法第一行顯式的通過super([參數(shù)列表]),調(diào)用父類的某一個(gè)有參構(gòu)造方法publicclassSup{publicSup(Stringarg){//父類中沒有無(wú)參構(gòu)造方法,只有有參構(gòu)造方法}}classSubextendsSup{publicSub(){super("argValue");//顯式的通過super([參數(shù)列表]),調(diào)用父類的有參構(gòu)造方法//..}}父類中沒有無(wú)參構(gòu)造器的兩種常見處理方式106先通過this([參數(shù)列表])調(diào)用本類中的其他構(gòu)造方法,再在其他構(gòu)造方法中通過super([參數(shù)列表])顯式的調(diào)用父類的構(gòu)造方法publicclassSup{publicSup(Stringarg){}}classSubextendsSup{publicSub(){this(1);//先調(diào)用本類的其他構(gòu)造方法}publicSub(inta){super("argValue");//再調(diào)用父類的構(gòu)造方法}}調(diào)用父類中被重寫的方法107但如何調(diào)用父類中被重寫的那個(gè)方法呢?使用super關(guān)鍵字,即可以使用super明確調(diào)用父類中的方法publicclassSup{publicvoidinfo(){}}classSubextendsSup{publicvoidinfo(){}publicvoidshow(){info();//或()。調(diào)用的是子類中的方法();//使用super調(diào)用父類中的方法}}調(diào)用父類中被重寫的方法108在使用super明確調(diào)用父類中的方法時(shí),一種常見的做法是,通過super對(duì)父類中已有的方法進(jìn)行補(bǔ)充classSubextendsSup{publicvoidinfo(){();//調(diào)用父類的info()System.out.println("thisissubclassinfo");//進(jìn)行一些額外的代碼補(bǔ)充}...}繼承相關(guān)問題的總結(jié)109對(duì)于“在子類繼承了父類后,子類繼承父類的方法”這一問題總結(jié)如下:子類可以直接沿用父類的方法;子類可以重寫父類的方法;子類可以在父類提供方法的基礎(chǔ)上,額外新增一些功能。super與this關(guān)鍵字的區(qū)別與聯(lián)系110super與this的區(qū)別如下:this代表當(dāng)前對(duì)象本身,而super代表父類對(duì)象。使用this可以調(diào)用當(dāng)前對(duì)象的屬性或方法,使用super可以調(diào)用父類對(duì)象的屬性或方法。使用this可以調(diào)用當(dāng)前類中的其他構(gòu)造方法,使用super可以調(diào)用父類中的構(gòu)造方法。super與this關(guān)鍵字的區(qū)別與聯(lián)系111super與this的聯(lián)系如下:super和this都指向一個(gè)對(duì)象,因此super和this的本質(zhì)都是引用。二者都可以調(diào)用類或?qū)ο蟮膶傩?、方法。在使用super()或this()調(diào)用構(gòu)造方法時(shí),都必須寫在構(gòu)造方法的第一行。因此,在一個(gè)構(gòu)造方法內(nèi)部,不可能同時(shí)使用super()和this()來(lái)調(diào)用其他的構(gòu)造方法。什么是多態(tài)112在漢語(yǔ)中經(jīng)常存在著“一詞多義”的情景。例如“打”這個(gè)字是什么意思呢?“打籃球”、“打水”、“打架”中“打”的含義各不相同,因此要想確定某個(gè)具體的“打”字的含義,就必須將“打”放入具體的語(yǔ)境,通過上下文來(lái)斷定。在程序開發(fā)中也存在著類似于這種“一詞多義”的特征——多態(tài)。向上轉(zhuǎn)型113見向上轉(zhuǎn)型,實(shí)際就是父類的引用指向子類對(duì)象,如下

父類引用=new子類();示例 Vehicle是父類,Car是子類

Vehiclev=newCar();動(dòng)態(tài)綁定與靜態(tài)綁定114動(dòng)態(tài)綁定是指在編譯期間方法并不會(huì)和“引用”的類型綁定在一起,而是在程序運(yùn)行的過程中,JVM需要根據(jù)具體的實(shí)例對(duì)象才能確定此時(shí)要調(diào)用的是哪個(gè)方法。重寫方法遵循的就是動(dòng)態(tài)綁定。例如,父類Sup和子類Sub都定義了info()方法,此時(shí)執(zhí)行以下代碼。Supx=newSub();();由于Sub類重寫了Sup中的info()方法,在編譯期間info()方法不會(huì)和任何一個(gè)具體的類綁定起來(lái),而是在運(yùn)行期間,會(huì)列舉出Sub類中info()的方法和從父類Sup繼承過來(lái)的info()方法,然后根據(jù)當(dāng)前的實(shí)例對(duì)象是Sub對(duì)象,選擇調(diào)用Sub類中的info()方法。動(dòng)態(tài)綁定與靜態(tài)綁定115有動(dòng)態(tài)綁定,自然就有靜態(tài)綁定。靜態(tài)綁定是指程序編譯期的綁定。以下的類信息,使用的就是靜態(tài)綁定機(jī)制:final、static或private修飾的方法,以及重載方法和構(gòu)造方法。成員變量。面向基類的編程思想116在程序設(shè)計(jì)時(shí),一種推薦的編程思想是“面向基類”編程。也就是建議將面向的“對(duì)象”抽象為更高層次的基類。例如,Car和Truct是子類,Vehicle是父類。那么不建議通過drive(Carcar)或drive(Trucktruck)等方法,限制方法接收的參數(shù)是某一個(gè)具體的對(duì)象類型,而建議將這些對(duì)象抽象成一個(gè)共同的基類,如drive(Vehiclevehicle),這樣一來(lái)就可以利用多態(tài)的特性方便的對(duì)程序進(jìn)行擴(kuò)展,不必每增加一個(gè)具體的子類就得新增一個(gè)具體的方法。例如drive(Vehiclevehicle)就可以接收任何Vehicle以及子類對(duì)象,因此可以大大減少代碼的冗余度。向上轉(zhuǎn)型的局限性117向上轉(zhuǎn)型雖然可以減少代碼量,增加程序的可擴(kuò)展性,但同時(shí)也有自身的問題。例如,在callShow(Vehiclev)方法中,只能調(diào)用Vehicle類的方法,不能調(diào)用Vehicle類子類特有的方法,這就是向上轉(zhuǎn)型的局限性。這個(gè)問題的解決辦法就是向下轉(zhuǎn)型。顧名思義,向下轉(zhuǎn)型就是將一個(gè)父類轉(zhuǎn)換成一個(gè)子類的動(dòng)作。但要注意的是,向下轉(zhuǎn)型不是自動(dòng)進(jìn)行的,需要人為的進(jìn)行強(qiáng)制類型轉(zhuǎn)換。保證強(qiáng)制轉(zhuǎn)換的準(zhǔn)確性118程序員編程的過程中,在進(jìn)行對(duì)象的強(qiáng)制類型轉(zhuǎn)換時(shí),如何保證轉(zhuǎn)換的正確性呢?可以使用Java提供的instanceof運(yùn)算符(不是方法)來(lái)進(jìn)行預(yù)判斷。instanceof運(yùn)算符的語(yǔ)法形式如下。 對(duì)象instanceof類該運(yùn)算符判斷一個(gè)對(duì)象是否屬于一個(gè)類,返回值為true或false。筆試題119下列關(guān)于繼承的哪項(xiàng)敘述是正確的()?A在java中類允許多繼承B在java中一個(gè)類只能實(shí)現(xiàn)一個(gè)接口C在java中一個(gè)類不能同時(shí)繼承一個(gè)類和實(shí)現(xiàn)一個(gè)接口Djava的單一繼承使代碼更可靠筆試題120關(guān)于this與super的區(qū)別下面那項(xiàng)描述是錯(cuò)誤的()?Athis和super都可以調(diào)用類中的屬性、方法、構(gòu)造方法Bsuper表示本類實(shí)例化對(duì)象,而this表示父類實(shí)例化對(duì)象C使用“this.屬性”或者“this.方法()”時(shí)都會(huì)先從本類查找方法,如果本類沒有定義,則通過父類查找D子類可以利用“super.方法()”調(diào)用父類方法筆試題121涉及類MyClass的方法簽名是:publicvoidfind(MyClassa),那么該方法不能接收的實(shí)際參數(shù)類型有()?AMyClass類型BMyClass的子類CObject類型DMyClass子類的子類筆試題122以下程序的運(yùn)行結(jié)果是()?classA{static{System.out,print(“1”);}publicA(){System.out.print(“2”);}}classBextendsA{static{System.out.print(“a”);}publicB(){System.out.print(“b”);}}publicclassHello{Publicstaticvoidmain(String[]ars){Aab=newB();ab=newB();}}Java程序設(shè)計(jì)基礎(chǔ)抽象類和接口抽象類和接口主要內(nèi)容1249.1抽象類(重點(diǎn))9.2接口(重點(diǎn))9.3內(nèi)部類教學(xué)目標(biāo)125能理解抽象類的概念及作用能理解接口的概念及作用能準(zhǔn)確區(qū)分接口繼承與類繼承的不同之處能準(zhǔn)確區(qū)分接口和抽象類的不同及聯(lián)系能使用接口和抽象類實(shí)現(xiàn)面向基類的編程思想能理解內(nèi)部類的概念及作用能正確使用成員內(nèi)部類,靜態(tài)內(nèi)部類,局部?jī)?nèi)部類、匿名內(nèi)部類等四種類型的內(nèi)部類能使用接口和抽象類提高程序的復(fù)用度抽象類簡(jiǎn)介126除了前面介紹的類以外,還存在一種特殊的類——抽象類。如果在類的定義中存在著一些抽象的方法,那么這種類就稱為抽象類。語(yǔ)法上,抽象類是不能用于實(shí)例化對(duì)象的。抽象類往往用來(lái)表示抽象概念。舉個(gè)例子,中國(guó)人(Chinese類)和美國(guó)人(American類)都有“吃飯”這個(gè)行為,因此可以先定義一個(gè)Person類,然后讓Chinese和American都繼承這個(gè)類。但如何在父類Person中定義“吃飯”這個(gè)方法呢?一般而言,中國(guó)人是用筷子吃飯,并且吃的是中餐;而美國(guó)人是用刀叉吃飯,吃的是西餐,顯然二者對(duì)于“吃飯”這一行為的具體實(shí)現(xiàn)是不同的。因此,無(wú)法在父類Person中具體的定義“吃飯”這一方法。此時(shí),就可以將Person定義成一個(gè)抽象類,并將“吃飯”這個(gè)行為定義成抽象方法(只有方法聲明,但沒有方法體的方法),然后再在子類Chinese和American中分別對(duì)“吃飯”進(jìn)行具體的實(shí)現(xiàn)。抽象類的語(yǔ)法形式127在面向?qū)ο蠓治龊驮O(shè)計(jì)的過程中,經(jīng)過封裝和繼承的分析之后,可以先創(chuàng)建一個(gè)抽象的父類,該父類定義了其所有子類共享的一般形式(如Person類),具體細(xì)節(jié)再由子類來(lái)完成(如Chinese類和American類)。Java中定義抽象類的語(yǔ)法形式如下。 abstractclass類名{}Java也提供了一種特殊的方法,這個(gè)方法不是一個(gè)完整的方法,只含有方法的聲明,沒有方法體,這樣的方法叫做抽象方法,其語(yǔ)法形式如下。 訪問修飾符abstract返回值方法名();抽象類的三個(gè)語(yǔ)法特征128抽象類不能被直接實(shí)例化抽象類的子類必須實(shí)現(xiàn)抽象方法(除非這個(gè)子類也是抽象類)抽象類里可以有普通方法,也可以有抽象方法,但是有抽象方法的類必須是抽象類。需要注意的是,抽象類里面也可以沒有抽象方法,只是把原來(lái)的類前面加上abstract關(guān)鍵字,使其變?yōu)槌橄箢?。例如,以下定義抽象類的代碼是符合語(yǔ)法規(guī)范的。接口簡(jiǎn)介129接口是一系列抽象方法的集合,與抽象類不同,不可以聲明普通方法。雖然有人常說(shuō),接口是一種特殊的抽象類,但是在面向?qū)ο缶幊痰脑O(shè)計(jì)思想層面,兩者還是有顯著區(qū)別的。抽象類更側(cè)重于對(duì)相似的類進(jìn)行抽象,形成抽象的父類以供子類繼承使用;而接口往往在程序設(shè)計(jì)的時(shí)候,定義模塊與模塊之間應(yīng)滿足的規(guī)約或者定義一種標(biāo)準(zhǔn),使各模塊之間能協(xié)調(diào)工作。接口的定義語(yǔ)法130Java接口定義的語(yǔ)法形式如下。 [修飾符]interface接口名[extends][接口列表]{接口體}interface前的修飾符是可選的,如果使用修飾符,則只能用public修飾符,表示此接口是公有的,在任何地方都可以引用它,這一點(diǎn)和類是相同的。接口是和類同一層次的,所以接口名的命名規(guī)則參考類名命名規(guī)則即可。extends關(guān)鍵詞和類語(yǔ)法中的extends類似,用來(lái)定義直接的父接口。和類不同,一個(gè)接口可以繼承多個(gè)父接口,當(dāng)extends

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論