java基礎(chǔ)知識(shí)點(diǎn)總結(jié)_第1頁
java基礎(chǔ)知識(shí)點(diǎn)總結(jié)_第2頁
java基礎(chǔ)知識(shí)點(diǎn)總結(jié)_第3頁
java基礎(chǔ)知識(shí)點(diǎn)總結(jié)_第4頁
java基礎(chǔ)知識(shí)點(diǎn)總結(jié)_第5頁
已閱讀5頁,還剩51頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

...wd......wd......wd...CreatedbyAIwenon2017/5/14.

java是面向?qū)ο蟮某绦蛟O(shè)計(jì)語言;類可被認(rèn)為是一種自定義的數(shù)據(jù)類型,可以使用類來定義變量,所有使用類定義的變量都是引用變量,它們將會(huì)引用到類的對(duì)象。類用于描述客觀世界里某一類對(duì)象的共同特征,而對(duì)象則是類的具體存在,java程序使用類的構(gòu)造器來創(chuàng)立該類的對(duì)象。

java也支持面向?qū)ο蟮娜筇卣鳎悍庋b、繼承、和多態(tài)。java提供了private、protected、和public三個(gè)訪問控制修飾符來實(shí)現(xiàn)良好的封裝,提供了extends關(guān)鍵字讓子類繼承父類,子類繼承父類就可以繼承到父類的成員變量和和方法,如果訪問控制允許,子類實(shí)例可以直接調(diào)用父類里定義的方法。繼承是實(shí)現(xiàn)類復(fù)用的重要手段。使用繼承關(guān)系來實(shí)現(xiàn)復(fù)用時(shí),子類對(duì)象可以直接賦給父類變量,這個(gè)變量具有多態(tài)性。

面向?qū)ο蟮某绦蛟O(shè)計(jì)過程中有兩個(gè)重要的概念:類〔Class)和對(duì)象〔object,也被稱為實(shí)例,instance〕。類可以包含三種最常見的成員:構(gòu)造器、成員變量、和方法。

構(gòu)造器用于構(gòu)造該類的實(shí)例,java語言通過new關(guān)鍵字類調(diào)用構(gòu)造器,從而返回該類的實(shí)例。構(gòu)造器是一個(gè)類創(chuàng)立對(duì)象的基本途徑,如果一個(gè)類沒有構(gòu)造器,這個(gè)類通常無法創(chuàng)立實(shí)例。因此java語言提供了一個(gè)功能:如果程序員沒有為一個(gè)類編寫構(gòu)造器,則系統(tǒng)會(huì)為該類提供一個(gè)默認(rèn)的構(gòu)造器,這個(gè)構(gòu)造器總是沒有參數(shù)的。一旦程序員為一個(gè)類提供了構(gòu)造器,系統(tǒng)將不再為該類提供構(gòu)造器。

構(gòu)造器用于對(duì)類實(shí)例進(jìn)展初始化操作,構(gòu)造器支持重載,如果多個(gè)重載的構(gòu)造器里包含了一樣的初始化代碼,則可以把這些初始化代碼放置在普通初始化塊里完成,初始化塊總在構(gòu)造器執(zhí)行之前被調(diào)用。靜態(tài)初始化塊代碼用于初始化類,在類初始化階段被執(zhí)行。如果繼承樹里某一個(gè)類需要被初始化時(shí),系統(tǒng)將會(huì)同時(shí)初始化該類的所有父類。構(gòu)造器修飾符:可以是public、protected、private其中之一,或者省略構(gòu)造器名:構(gòu)造器名必須和類名一樣。

注意:構(gòu)造器既不能定義返回值類型,也不能使用void聲明構(gòu)造器沒有返回值。如果為構(gòu)造器定義了返回值類型,或使用void聲明構(gòu)造器沒有返回值,編譯時(shí)不會(huì)出錯(cuò),但java會(huì)把這個(gè)所謂的構(gòu)造器當(dāng)成方法來處理——它就不再是構(gòu)造器。

實(shí)際上類的構(gòu)造器是有返回值的,當(dāng)使用new關(guān)鍵字來調(diào)用構(gòu)造器時(shí),構(gòu)造器返回該類的實(shí)例,可以把這個(gè)類的實(shí)例當(dāng)成構(gòu)造器的返回值。因此構(gòu)造器的返回值類型總是當(dāng)前類,無須定義返回值類型。不要在構(gòu)造器里顯式的使用return來返回當(dāng)前類的對(duì)象,因?yàn)闃?gòu)造器的返回值是隱式的。

java類名必須是由一個(gè)或多個(gè)有意義的單詞連綴而成的,每個(gè)單詞首字母大寫,其他字母全部小寫,單詞與單詞之間不要使用任何分隔符。

成員變量:

成員變量的修飾符:public、protected、private、static、final前三個(gè)只能出現(xiàn)一個(gè)再和后面的修飾符組合起來修飾成員變量,也可省略。

成員變量:由一個(gè)或者多個(gè)有意義的單詞連綴而成,第一個(gè)單詞首字母小寫,后面每個(gè)單詞首字母大寫,其他字母全部小寫,單詞與單詞之間不要使用任何分隔符。類型:可以是java語言允許的任何數(shù)據(jù)類型,包括基本類型和引用類型。

成員方法:

方法修飾符:public、protected、private、static、final、abstract,前三個(gè)只能出現(xiàn)一個(gè),static和final最多只能出現(xiàn)其中的一個(gè),和abstract組合起來使用。也可省略。

返回值類型:可以是java語言的允許的任何數(shù)據(jù)類型,包括基本類型和引用類型。

方法名:和成員變量的方法命名規(guī)則一樣,通常建議方法名以英文動(dòng)詞開頭。

方法體里多條可執(zhí)行語句之間有嚴(yán)格的執(zhí)行順序,排在方法體前面的語句總先執(zhí)行,排在方法體后面的語句總是后執(zhí)行。

static是一個(gè)特殊的關(guān)鍵字,它可用于修飾方法、成員變量等成員。static修飾的成員說明它屬于這個(gè)類本身,而不屬于該類的單個(gè)實(shí)例,因此通過把static修飾的成員變量和方法被稱為類變量、類方法〔靜態(tài)成員變量,靜態(tài)成員方法〕;不使用static修飾的成員變量和方法稱為實(shí)例變量和實(shí)例方法〔非靜態(tài)成員變量,非靜態(tài)成員方法〕。靜態(tài)成員不能直接訪問非靜態(tài)成員。

static的真正作用就是用于區(qū)分成員變量、方法、內(nèi)部類、初始化塊,這四種成員到底屬于類本身還是屬于實(shí)例。有static修飾的成員屬于類本身,沒有類修飾的成員屬于該類的實(shí)例。

java類大致有如下作用:定義變量

創(chuàng)立對(duì)象

調(diào)用類的類方法或訪問類的類變量。定義一個(gè)類就是為了重復(fù)創(chuàng)立該類的實(shí)例,同一個(gè)類的多個(gè)實(shí)例具有一樣的特征,而類則是定義了多個(gè)實(shí)例的共同特征。類里定義的方法和成員變量都可以通過類或?qū)嵗齺碚{(diào)用。Static修飾的方法和成員變量,既可通過類來調(diào)用,也可通過實(shí)例來調(diào)用;沒有使用static修飾的普通方法成員變量,只可通過實(shí)例來調(diào)用。Personp=newPerson();這行代碼創(chuàng)立了一個(gè)Person實(shí)例,也被稱為Person對(duì)象,這個(gè)Person對(duì)象被賦給p變量。在這行代碼中實(shí)際上產(chǎn)生了兩個(gè)東西,一個(gè)是p變量,一個(gè)是Person對(duì)象。P引用變量本身只存儲(chǔ)了一個(gè)地址值,并未包含任何實(shí)際數(shù)據(jù),但它指向?qū)嶋H的Person對(duì)象。Person對(duì)象由多塊內(nèi)存組成,不同內(nèi)存塊分別存儲(chǔ)了Person對(duì)象的不同成員變量。類是一種引用數(shù)據(jù)類型,因此程序中定義的Person類型的變量實(shí)際上是一個(gè)引用,它被存放在棧內(nèi)存里,指向?qū)嶋H的Person對(duì)象;而真正的Person對(duì)象則存放在堆內(nèi)存中。當(dāng)一個(gè)對(duì)象被創(chuàng)立成功以后,這個(gè)對(duì)象將保存在堆內(nèi)存中,java程序不允許直接訪問堆內(nèi)存中的對(duì)象,只能通過該對(duì)象的引用操作該對(duì)象。堆內(nèi)存里的對(duì)象可以有多個(gè)引用,即多個(gè)引用變量指向同一個(gè)對(duì)象。如果堆內(nèi)存里的對(duì)象沒有任何變量指向該對(duì)象,那么程序?qū)o法再訪問該對(duì)象,這個(gè)對(duì)象也就變成了垃圾,java垃圾回收機(jī)制將回收該對(duì)象,釋放該對(duì)象所占的內(nèi)存區(qū)。對(duì)象的this引用Java提供了一個(gè)this關(guān)鍵字,this關(guān)鍵字總是指向調(diào)用該方法的對(duì)象。This作為對(duì)象的默認(rèn)引用有兩種情形:構(gòu)造器中引用該構(gòu)造器正在初始化的對(duì)象;在方法中引用調(diào)用該方法的對(duì)象。This關(guān)鍵字最大的作用就是讓類中一個(gè)方法,訪問該類里的另一個(gè)方法或者實(shí)例變量。Java允許對(duì)象的一個(gè)成員直接調(diào)用另一個(gè)成員,可以省略this 前綴。如果在static修飾的方法中使用this關(guān)鍵字,則這個(gè)關(guān)鍵字就無法指向適宜的對(duì)象,所以,static修飾的方法中不能使用this引用。Java編程時(shí)不要使用對(duì)象去調(diào)用static修飾的成員變量、方法、而是應(yīng)該使用類去調(diào)用static修飾的成員變量、方法。如果確實(shí)需要在靜態(tài)方法中訪問另一個(gè)普通方法,則只能重新創(chuàng)立一個(gè)對(duì)象。大局部的時(shí)候,普通方法訪問其他方法、成員變量時(shí)無須使用this前綴,但如果方法里有個(gè)局部變量和成員變量同名,但程序又需要在該方法里訪問這個(gè)被覆蓋的成員變量,則必須使用this前綴。This引用也可以用于構(gòu)造器中作為默認(rèn)引用,由于構(gòu)造器時(shí)直接使用new關(guān)鍵字來調(diào)用,而不是使用對(duì)象來調(diào)用的,所以this在構(gòu)造器中代表該構(gòu)造器正在初始化對(duì)象。方法:Java里的方法不能獨(dú)立存在,所有的方法都必須定義在類里。如果這個(gè)方法是用來static修飾,則這個(gè)方法屬于這個(gè)類,否則這個(gè)方法屬于這個(gè)類的實(shí)例。執(zhí)行方法時(shí),必須使用類或者對(duì)象作為調(diào)用者。同一個(gè)類的一個(gè)方法調(diào)用另外一個(gè)方法時(shí),如果被調(diào)方法是普通方法,則默認(rèn)使用this作為調(diào)用者;如果被調(diào)用方法是靜態(tài)方法,則默認(rèn)使用類作為調(diào)用者。也就是說java中看起來某些方法可以被獨(dú)立執(zhí)行,但實(shí)際上還是使用this或者類來作為調(diào)用者。Java里方法參數(shù)傳遞方式只有一種:值傳遞。所謂值傳遞,就是講實(shí)際參數(shù)值的副本〔復(fù)制品〕傳入方法內(nèi),而參數(shù)本身不會(huì)受到任何影響。從JDK1.5之后,java允許定義形參個(gè)數(shù)可變的參數(shù),從而允許為方法指定數(shù)量不確定的形參。如果在定義方法時(shí),在最后一個(gè)形參的類型后增加三點(diǎn)〔…〕,則說明該形參可以承受多個(gè)參數(shù)值,多個(gè)參數(shù)值被當(dāng)成數(shù)組傳入。publicclassVarargs{

//定義形參可變的方法

publicstaticvoidtest(inta,String...books){

//books被當(dāng)成數(shù)組處理

for(Stringtmp:books){

System.out.println(tmp);

}

System.out.println(a);

}

publicstaticvoidmain(String[]args){

//調(diào)用test方法

test(5,"hello","world","aa");

}

}數(shù)組形式的形參可以處于形參列表的任意位置,但個(gè)數(shù)可變的形參只能處于形參表的最后。也就是說最多只能有一個(gè)長度可變的形參。形參可變和傳入數(shù)組的區(qū)別:publicstaticvoidtest(inta,String...books);

publicstaticvoidtest(inta,String[]books);

test(5,"aa","bb","cc");

test(5,newString[]{"aa","bb","cc"});方法重載:Java允許同一個(gè)類里定義多個(gè)同名方法,只要形參列表不同就行。如果同一個(gè)類中包含了兩個(gè)或兩個(gè)以上方法的方法名一樣,但形參列表不同,則被稱為方法的重載。Java程序確定一個(gè)方法需要三個(gè)要素:調(diào)用者;方法名;形參列表。方法的重載要求就是兩同一不同:同一個(gè)類中方法名一樣,參數(shù)列表不同。至于方法的其他局部,如方法返回值類型、修飾符等,與方法重載沒有任何關(guān)系。publicclassOverloadVarargs{

publicvoidtest(Stringmsg){

System.out.println("只有一個(gè)參數(shù)的test");

}

//因?yàn)榍懊嬉呀?jīng)有了一個(gè)字符串參數(shù)的方法,則長度可變形參里不包含一個(gè)字符串參數(shù)的形式

publicvoidtest(String...books){

System.out.println("形參可變的test方法");

}

publicstaticvoidmain(String[]args){

OverloadVarargsolv=newOverloadVarargs();

//下面兩次調(diào)用將執(zhí)行第二個(gè)test方法

olv.test();

olv.test("aa","bb");

//將調(diào)用第一個(gè)test方法

olv.test("aa");

//將調(diào)用第二個(gè)test方法

olv.test(newString[]{"aa"});

}

}Java中變量分為:成員變量和局部變量。成員變量被分為類變量和實(shí)例變量兩種,定義成員變量時(shí)沒有static修飾的就是實(shí)例變量,有static修飾的就是類變量。變量的命名:從程序的可讀性角度來看,應(yīng)該是多個(gè)有意義的單詞連綴而成,其中第一個(gè)單詞首字母小寫,后面每個(gè)單詞首字母大寫。如果通過一個(gè)實(shí)例修改了類變量的值,由于這個(gè)類變量并不屬于它,而是屬于它對(duì)應(yīng)的類。因此,修改的依然是類變量,與通過該類來修改類變量的結(jié)果完全一樣,這會(huì)導(dǎo)致該類的其他實(shí)例來訪問這個(gè)類變量時(shí)也將獲得這個(gè)被修改正的值。成員變量無須顯式初始化,只要為一個(gè)類定義了類變量或?qū)嵗兞?,系統(tǒng)就會(huì)在這個(gè)類的初始化階段或創(chuàng)立該類的實(shí)例時(shí),進(jìn)展默認(rèn)初始化。實(shí)例變量隨實(shí)例的存在而存在,而類變量則隨類的存在而存在。實(shí)例也可訪問類變量,同一個(gè)類的所有實(shí)例訪問類變量時(shí),實(shí)際上訪問的是該類本身的同一個(gè)變量,也就是說,訪問了同一片內(nèi)存區(qū)。局部變量根據(jù)定義形式的不同,又可分為三種形式:形參,方法局部變量,代碼塊局部變量;局部變量除了形參之外,都必須顯示初始化。在同一個(gè)類里,成員變量的作用范圍是整個(gè)類內(nèi)有效,一個(gè)類里不能定義兩個(gè)同名的成員變量,即使一個(gè)是類變量,一個(gè)是實(shí)例變量也不行;一個(gè)方法里不能定義兩個(gè)同名的方法局部變量,方法局部變量與形參也不能同名;同一個(gè)方法中不同代碼塊內(nèi)局部變量可以同名;如果先定義代碼塊局部變量,后定義方法局部變量,前面定義的代碼塊局部變量與后面定義的方法局部變量也可同名.Java允許局部變量和成員變量同名,如果方法里的局部變量和成員變量同名,局部變量會(huì)覆蓋成員變量,如果需要在這個(gè)方法里引用被覆蓋的成員變量,則可使用this(對(duì)于實(shí)例變量)或類名〔對(duì)于類變量〕作為調(diào)用者來限定訪問成員變量。publicclassVariableOverrideTest{

//定義一個(gè)name實(shí)例變量

privateStringname="李剛";

//定義一個(gè)price類變量

privatestaticdoubleprice=78.0;

publicstaticvoidmain(String[]args){

//方法里局部變量覆蓋成員變量,將輸出price的局部變量65

intprice=65;

System.out.println(price);

//使用類名作為price變量的限定,將輸出price類變量的值

System.out.println(VariableOverrideTest.price);

newVariableOverrideTest().info();

}

publicvoidinfo(){

//方法里的局部變量,局部變量覆蓋成員變量,輸出name局部變量的值:孫悟空

Stringname="孫悟空";

System.out.println(name);

//將輸出name實(shí)例的值:李剛

System.out.println();

}

}當(dāng)系統(tǒng)加載類或創(chuàng)立該類的實(shí)例時(shí),系統(tǒng)自動(dòng)為成員變量分配內(nèi)存空間,并在分配內(nèi)存空間后,自動(dòng)為成員變量指定初始值。Personp1=newPerson();時(shí),如果這行代碼是第一次使用Person類,則系統(tǒng)通常會(huì)在第一次使用Person類時(shí)加載這個(gè)類,并初始化這個(gè)類。局部變量定以后,必須經(jīng)過顯式初始化后才能使用,系統(tǒng)不會(huì)為局部變量執(zhí)行初始化。局部變量不屬于任何類或者實(shí)例,因此它總是保存在其所在方法的棧內(nèi)存中。如果局部變量時(shí)基本類型的變量,則直接把這個(gè)變量的值保存在該變量對(duì)應(yīng)的內(nèi)存中;如果局部變量是一個(gè)引用類型的變量,則這個(gè)變量里存放的是地址,通過該地址引用到該變量實(shí)際引用的對(duì)象或者數(shù)組。棧內(nèi)存中的變量無須系統(tǒng)垃圾回收,往往隨是方法或代碼塊的運(yùn)行完畢而完畢。如果定義的某個(gè)變量是用于描述某個(gè)類或某個(gè)對(duì)象的固有信息的,這種變量應(yīng)該定義成成員變量。如果這種信息對(duì)這個(gè)類的所有實(shí)例完全一樣,或者說它是類相關(guān)的,則該定義成類變量;如果這個(gè)信息是實(shí)例相關(guān)的,則應(yīng)該定義成實(shí)例變量。用于保存某個(gè)類或某個(gè)實(shí)例狀態(tài)信息的變量通常應(yīng)該使用成員變量。如果某個(gè)信息需要在某個(gè)類的多個(gè)方法之間進(jìn)展共享,則這個(gè)信息應(yīng)該使用成員變量來保存。隱藏和封裝訪問控制符用于控制一個(gè)類的成員是否可以被其他類訪問。Java提供了3個(gè)訪問控制修飾符:private,protected,和public,還有一個(gè)默認(rèn)訪問控制修飾符defaultPrivate(當(dāng)前類訪問權(quán)限);default〔包訪問權(quán)限〕;protected〔子類訪問權(quán)限〕:如果一個(gè)成員使用protected訪問修飾符修飾,那么這個(gè)成員既可以被同一個(gè)包中的其他類訪問,也可以被不同包中子類訪問。通常情況下,使用protected修飾的方法,通常希望其子類來重寫這個(gè)方法。Public〔公共訪問權(quán)限〕對(duì)于局部變量而言,其作用域就是它所在的方法,不可能被其他類訪問,因此不能使用訪問控制符來修飾。外部類只能有兩種訪問控制級(jí)別:public和默認(rèn),不能使用private和protectedpublicclassPerson{

privateStringname;

privateintage;

publicvoidsetName(Stringname){

if(name.length()>6||name.length()<2){

System.out.println("error");

return;

}

else{

=name;

}

}

publicStringgetName(){

return;

}

publicvoidsetAge(intage){

if(age>100||age<0){

System.out.println("error");

}else{

this.age=age;

}

}

publicintgetAge(){

returnthis.age;

}

}publicclassPersonTest{

publicstaticvoidmain(String[]args){

Personp=newPerson();

//下面的變量不會(huì)運(yùn)行錯(cuò)誤,但是會(huì)提示錯(cuò)誤

p.setAge(1000);

//因?yàn)樯厦鏇]有成功設(shè)置p的age成員,故輸出0

System.out.println(p.getAge());

//成功設(shè)置p的age成員

p.setAge(30);

System.out.println(p.getAge());

//成功設(shè)置p的name成員

p.setName("李剛");

System.out.println(p.getName());

}

}構(gòu)造器:構(gòu)造器最大的用途是創(chuàng)立對(duì)象時(shí)執(zhí)行初始化。當(dāng)創(chuàng)立一個(gè)對(duì)象時(shí),系統(tǒng)為這個(gè)對(duì)象的實(shí)例變量進(jìn)展默認(rèn)初始化,這種默認(rèn)的初始化把所有基本類型的實(shí)例變量設(shè)為0〔對(duì)數(shù)值型實(shí)例變量〕或false〔對(duì)布爾型實(shí)例變量〕,把所有引用類型的實(shí)例變量設(shè)為null。如果想改變這種默認(rèn)的初始化,想讓系統(tǒng)創(chuàng)立對(duì)象時(shí)就位該對(duì)象的實(shí)例變量顯式指定初始值,就可以通過構(gòu)造器來實(shí)現(xiàn)。因?yàn)闃?gòu)造器主要用于被其他方法調(diào)用,用以返回該類的實(shí)例,因而通常把構(gòu)造器設(shè)置成public訪問權(quán)限,從而允許系統(tǒng)中任何位置的類來創(chuàng)立該類的對(duì)象。如果設(shè)置成protected,主要用于被子類調(diào)用;設(shè)置為private,阻止其他類創(chuàng)立該類的實(shí)例。如果系統(tǒng)中包含了多個(gè)構(gòu)造器,其中一個(gè)構(gòu)造器B的執(zhí)行體里完全包含另一個(gè)構(gòu)造器A的執(zhí)行體。為了這構(gòu)造器B中調(diào)用構(gòu)造器A中的初始化代碼,又不會(huì)重新創(chuàng)立一個(gè)java對(duì)象,可以使用this關(guān)鍵字來調(diào)用相應(yīng)的構(gòu)造器。publicclassApple{

publicStringname;

publicStringcolor;

publicdoubleweight;

//兩個(gè)參數(shù)的構(gòu)造器

publicApple(Stringname,Stringcolor){

=name;

this.color=color;

}

//三個(gè)參數(shù)的構(gòu)造器

publicApple(Stringname,Stringcolor,doubleweight){

//通過this調(diào)用另一個(gè)重載的構(gòu)造器的初始化代碼

this(name,color);

//通過this引用該構(gòu)造器正在初始化的Java對(duì)象

this.weight=weight;

}

}使用this調(diào)用另一個(gè)重載的構(gòu)造器只能在構(gòu)造器中使用,而且必須作為構(gòu)造器執(zhí)行體的第一條語句。使用this調(diào)用重載的構(gòu)造器時(shí),系統(tǒng)會(huì)根據(jù)this后括號(hào)里的實(shí)參來調(diào)用形參列表與之對(duì)應(yīng)的構(gòu)造器類的繼承:Java繼承通過extends關(guān)鍵字來實(shí)現(xiàn)實(shí)現(xiàn)繼承的類被稱為子類,被繼承的類被稱為父類,有的也稱為基類、超類。因?yàn)樽宇愂且环N特殊的父類,因此父類包含的范圍總比子類包含的范圍要大。Java子類不能獲得父類的構(gòu)造器publicclassFruit{

publicdoubleweight;

publicvoidinfo(){

System.out.println(weight);

}

}publicclassAppleextendsFruit{//Apple類繼承了Fruit類,所以Apple對(duì)象也就有了weight成員變量和info()方法

publicstaticvoidmain(String[]args){

Applea=newApple();

//Apple對(duì)象本身沒有weight成員變量,但是,Apple父類有weight成員變量,所以,也可以訪問Apple對(duì)象的weight成員變量

a.weight=56;

//調(diào)用Apple對(duì)象的info()方法

();

}

}Java類只能有一個(gè)直接父類,實(shí)際上,Java類可以有無限多個(gè)間接父類。重寫父類方法:子類擴(kuò)展了父類,子類是一個(gè)特殊的父類。大局部時(shí)候,子類總是以父類為根基,額外增加新的成員變量和方法。但有一種情況例外:子類需要重寫父類方法。publicclassBird{

//Bird類的fly()方法

publicvoidfly(){

System.out.println("我在天空中飛");

}

}publicclassOstrichextendsBird{

//重寫B(tài)ird類的fly()方法

publicvoidfly(){

System.out.println("我在陸地上飛");

}

publicstaticvoidmain(String[]args){

//創(chuàng)立Ostrich對(duì)象

Ostrichor=newOstrich();

//執(zhí)行Ostrich對(duì)象的fly〔〕方法,將輸出“我在陸地上飛〞

or.fly();

}

}這種子類包含與父類同名方法的現(xiàn)象被稱為方法重寫〔Override〕,也被稱為方法覆蓋??梢哉f子類重寫了父類的方法,也可以說子類覆蓋了父類的方法。方法的重寫要遵循“兩同兩小一大〞規(guī)則,“兩同〞即方法名一樣、形參列表一樣;“兩小〞指的是子類方法的返回值類型應(yīng)比父類方法返回值類型更小或相等,子類方法聲明拋出的異常類應(yīng)比父類聲明拋出的異常類更小或相等;“一大〞指的是子類方法的訪問權(quán)限應(yīng)比父類方法的訪問權(quán)限更大或相等。覆蓋方法和被覆蓋方法要么都是類方法,要么都是實(shí)例方法。當(dāng)子類覆蓋了父類方法后,子類的對(duì)象將無法訪問父類中被覆蓋的方法,但可以在子類方法中調(diào)用被覆蓋的方法。如果需要在子類方法中調(diào)用父類中被覆蓋的方法,則可以使用super〔被覆蓋的是實(shí)例方法〕或者父類類名〔被覆蓋的是類方法〕作為調(diào)用者來調(diào)用父類中被覆蓋的方法。如果父類方法具有private訪問權(quán)限,則該方法對(duì)其子類是隱藏的,因此其子類無法訪問該方法,也就是無法重寫該方法。重載只要發(fā)生在同個(gè)類多個(gè)同名方法之間,而重寫發(fā)生在子類和父類同名方法之間。父類方法和子類方法之間也可能發(fā)生重載。Super限定:Super是Java提供的一個(gè)關(guān)鍵字,super用于限定該對(duì)象調(diào)用它從父類繼承得到的實(shí)例變量或方法。Super不能出現(xiàn)在static修飾的方法中。Static修飾的方法是屬于類的,該方法的調(diào)用者可能是一個(gè)類,而不是對(duì)象,因而super限定就失去了意義。如果在構(gòu)造器中使用super,則super用于限定該構(gòu)造器初始化的是該對(duì)象從父類繼承得到的實(shí)例變量,而不是該類自己定義的實(shí)例變量。如果子類定義了和父類同名的實(shí)例變量,則會(huì)發(fā)生子類實(shí)例變量隱藏父類實(shí)例變量的情形。在正常情況下,子類里定義的方法直接訪問該實(shí)例變量,默認(rèn)會(huì)訪問到子類中定義的實(shí)例變量,無法訪問到父類中被隱藏的實(shí)例變量。在子類定義的實(shí)例方法中可以通過super來訪問父類中被隱藏的實(shí)例變量。publicclassBaseClass{

publicinta=5;

}publicclassSubClassextendsBaseClass{

publicinta=7;

publicvoidaccessOwner(){

System.out.println(a);

}

publicvoidaccessBase(){

//通過super來限定訪問從父類繼承得到的a實(shí)例變量

System.out.println(super.a);

}

publicstaticvoidmain(String[]args){

SubClasssb=newSubClass();

sb.accessBase();//輸出5

sb.accessOwner();//輸出7

}

}如果在某個(gè)方法中訪問名為a的成員變量,但沒有顯式指定調(diào)用者,則系統(tǒng)查找a的順序?yàn)椋翰檎以摲椒ㄖ惺欠裼忻麨閍的局部變量查找當(dāng)前類中是否包含名為a的成員變量查找a的直接父類中是否包含名為a的成員變量,一次上溯a的所有父類,直到j(luò)ava.lang.Object類,如果最終不能找到名為a的成員變量,則系統(tǒng)出現(xiàn)編譯錯(cuò)誤。如果被覆蓋的是類變量,在子類的方法中則可以通過父類名作為調(diào)用者來訪問被覆蓋的類變量當(dāng)程序創(chuàng)立一個(gè)子類對(duì)象時(shí),系統(tǒng)不僅會(huì)為該類中定義的實(shí)例變量分配內(nèi)存,也會(huì)為它從父類繼承得到的所有實(shí)例變量分配內(nèi)存,即使子類定義了與父類中同名的實(shí)例變量。如果在子類里定義了與父類中已有變量同名的變量,那么子類中定義的變量會(huì)隱藏父類中定義的變量。注意不是完全覆蓋,因此系統(tǒng)在創(chuàng)立子類對(duì)象時(shí),依然會(huì)為父類中定義的、被隱藏的變量分配內(nèi)存空間。publicclassParent{

publicStringtag="helloworld";

}publicclassDerivedextendsParent{

//定義一個(gè)私有的tag實(shí)例變量來隱藏父類的tag實(shí)例變量

privateStringtag="abc";

}publicclassHideTest{

publicstaticvoidmain(String[]args){

Derivedd=newDerived();

//程序不可訪問d的私有變量tag,所以會(huì)出現(xiàn)編譯錯(cuò)誤

//System.out.println(d.tag);

//將d變量顯式的向上轉(zhuǎn)型為Parent后,即可訪問tag實(shí)例變量

System.out.println(((Parent)d).tag);

}

}調(diào)用父類構(gòu)造器:子類不會(huì)獲得父類的構(gòu)造器,但子類構(gòu)造器里可以調(diào)用父類構(gòu)造器的初始化代碼。在一個(gè)構(gòu)造器里調(diào)用另一個(gè)重載的構(gòu)造器使用this調(diào)用來完成,在子類構(gòu)造器中調(diào)用父類構(gòu)造器使用super調(diào)用來完成。publicclassBase{

publicdoublesize;

publicStringname;

publicBase(doublesize,Stringname){

this.size=size;

=name;

}

}publicclassSubextendsBase{

publicStringcolor;

publicSub(doublesize,Stringname,Stringcolor){

//通過super調(diào)用父類構(gòu)造器的初始化過程

super(size,name);

this.color=color;

}

publicstaticvoidmain(String[]args){

Subs=newSub(5.6,"測試","red");

System.out.println(s.size+","++","+s.color);

}

}Super調(diào)用的是其父類的構(gòu)造器,而this調(diào)用的是同一個(gè)類中重載的構(gòu)造器;因此,使用super調(diào)用父類的構(gòu)造器也必須出現(xiàn)在子類構(gòu)造器執(zhí)行體的第一行,所以this調(diào)用和super調(diào)用不會(huì)同時(shí)出現(xiàn)。當(dāng)調(diào)用子類構(gòu)造器來初始化子類對(duì)象時(shí),父類構(gòu)造器總會(huì)在子類構(gòu)造器之前執(zhí)行;不僅如此,執(zhí)行父類構(gòu)造器時(shí),系統(tǒng)會(huì)再次上溯執(zhí)行其父類的構(gòu)造器……依次類推,創(chuàng)立任何java對(duì)象,最先執(zhí)行的總是java.lang.Object類的構(gòu)造器。publicclassCreature{

publicCreature(){

System.out.println("無參");

}

}publicclassAnimalextendsCreature{

publicAnimal(Stringname){

System.out.println("Animal帶一個(gè)參數(shù)的構(gòu)造器"+name);

}

publicAnimal(Stringname,intage){

//this調(diào)用同一個(gè)重載構(gòu)造器

this(name);

System.out.println("Animal帶兩個(gè)參數(shù)的構(gòu)造器"+age);

}

}publicclassWolfextendsAnimal{

publicWolf(){

super("灰太狼",4);

System.out.println("wolf無參構(gòu)造器");

}

publicstaticvoidmain(String[]args){

Wolfwf=newWolf();

//雖然main方法只創(chuàng)立了一個(gè)Wolf對(duì)象,但系統(tǒng)在底層完成了復(fù)雜的操作,運(yùn)行將會(huì)得到

//無參

//Animal帶一個(gè)參數(shù)的構(gòu)造器灰太狼

//Animal帶兩個(gè)參數(shù)的構(gòu)造器4

//wolf無參構(gòu)造器

}

}創(chuàng)立任何對(duì)象總是從該類所在繼承樹最頂層類的構(gòu)造器開場執(zhí)行,然后依次向下執(zhí)行,最后才執(zhí)行本類的構(gòu)造器。如果某個(gè)父類通過this調(diào)用了同類中重載的構(gòu)造器,就會(huì)依次執(zhí)行此父類的多個(gè)構(gòu)造器。4.7多態(tài):Java引用變量有兩個(gè)類型:一個(gè)是編譯時(shí)類型,一個(gè)是運(yùn)行時(shí)類型。編譯時(shí)類型由聲明該變量時(shí)使用的類型決定,運(yùn)行時(shí)類型由實(shí)際賦給該變量的對(duì)象決定。如果編譯時(shí)類型和運(yùn)行時(shí)類型不一致,就可能出現(xiàn)所謂的多態(tài)。publicclassBaseClass{

publicintbook=6;

publicvoidbase(){

System.out.println("父類的普通方法");

}

publicvoidtest(){

System.out.println("父類被覆蓋的方法");

}

}publicclassSubClassextendsBaseClass{

//重寫定義一個(gè)book實(shí)例變量隱藏父類的book實(shí)例變量

publicStringbook="abc";

publicvoidtest(){

System.out.println("子類的覆蓋父類的方法");

}

publicvoidsub(){

System.out.println("子類的普通方法");

}

publicstaticvoidmain(String[]args){

//編譯時(shí)類型和運(yùn)行時(shí)類型完全一樣,因此不存在多態(tài)

BaseClassbc=newBaseClass();

//輸出父類bc對(duì)象的成員變量值:6

System.out.println(bc.book);

bc.test();

bc.base();

//編譯時(shí)類型和運(yùn)行時(shí)類型完全一樣,因此不存在多態(tài)

SubClasssbc=newSubClass();

//輸出子類對(duì)象sbc的成員變量值:abc

System.out.println(sbc.book);

sbc.test();

sbc.sub();

//下面調(diào)用將執(zhí)行從父類繼承到的base()方法

sbc.base();

//編譯時(shí)類型和運(yùn)行時(shí)類型不一樣,發(fā)生多態(tài)發(fā)生

BaseClassployBc=newSubClass();

//訪問的是父類對(duì)象的實(shí)例變量

System.out.println(ployBc.book);

//執(zhí)行從父類繼承到的base()方法

ployBc.base();

//調(diào)用將執(zhí)行當(dāng)前類的test()方法

ployBc.test();

//ployBc.sub();因?yàn)榫幾g時(shí)類型是BaseClass,沒有提供sub()方法,所以編譯會(huì)出現(xiàn)錯(cuò)誤

}

}因?yàn)樽宇愂且环N特殊的父類,因此java允許把一個(gè)子類對(duì)象直接賦給一個(gè)父類引用變量,無須任何類型轉(zhuǎn)換,或者被稱為向上轉(zhuǎn)型,向上轉(zhuǎn)型由系統(tǒng)自動(dòng)完全。對(duì)象的實(shí)例變量不具備多態(tài)性。注:引用變量在編譯階段只能調(diào)用其編譯時(shí)類型所具有的方法,但運(yùn)行時(shí)則執(zhí)行它運(yùn)行時(shí)類型所具有的方法。因此在編寫Java代碼時(shí),引用變量只能調(diào)用聲明該變量時(shí)所用類里包含的方法。例如:Objectp=newPerson()代碼定義了一個(gè)變量P,則這個(gè)P只能調(diào)用Object類的方法,而不能調(diào)用Person類里的方法。如果需要讓這個(gè)引用變量調(diào)用它運(yùn)行時(shí)類型的方法,則必須把它強(qiáng)制類型轉(zhuǎn)化成運(yùn)行時(shí)的類型,強(qiáng)制類型轉(zhuǎn)換符需要借助于類型轉(zhuǎn)換運(yùn)算符,用法是〔type〕variable強(qiáng)制類型轉(zhuǎn)換需要注意:基本類型之間的轉(zhuǎn)換只能在數(shù)值類型之間進(jìn)展,這里所說的數(shù)值類型包括,整數(shù)型、字符型和浮點(diǎn)型;但數(shù)值類型和布爾類型之間不能進(jìn)展類型轉(zhuǎn)換。引用類型之間的轉(zhuǎn)換只能在具有繼承關(guān)系的兩個(gè)類型之間進(jìn)展,如果是兩個(gè)沒有任何繼承關(guān)系的類型,則無法進(jìn)展類型轉(zhuǎn)換??紤]到強(qiáng)制類型轉(zhuǎn)換時(shí)可能出現(xiàn)異常,因此進(jìn)展類型轉(zhuǎn)換之前應(yīng)先通過instanceof運(yùn)算符來判斷是否可以成功轉(zhuǎn)換。注意:當(dāng)把子類對(duì)象賦給父類引用變量時(shí),被稱為向上轉(zhuǎn)型,這種轉(zhuǎn)型總是可以成功的,這也從另一個(gè)側(cè)面證實(shí)了子類是一種特殊的父類。這種轉(zhuǎn)型只是說明這個(gè)引用變量的編譯時(shí)類型是父類,但實(shí)際執(zhí)行它的方法時(shí),依然表現(xiàn)出子類對(duì)象行為方式。但把一個(gè)父類對(duì)象賦給子類引用變量時(shí),就需要進(jìn)展強(qiáng)制類型轉(zhuǎn)換,而且還可能在運(yùn)行時(shí)產(chǎn)生ClassCastException異常,使用instanceof運(yùn)算符可以讓強(qiáng)制類型轉(zhuǎn)換更安全。Instanceof運(yùn)算符:Instanceof運(yùn)算符前一個(gè)操作數(shù)通常是一個(gè)引用類型變量,后一個(gè)操作數(shù)通常是一個(gè)類〔也可以是接口〕,它用于判斷前面的對(duì)象是否是后面的類,或者其子類、實(shí)現(xiàn)的實(shí)例。如果是,則返回ture,否則返回false.在使用instanceof運(yùn)算符時(shí)需要注意:instanceof運(yùn)算符前面操作數(shù)的編譯時(shí)類型要么與后面的類一樣,要么與后面的類具有父子繼承關(guān)系,否則會(huì)引起編譯錯(cuò)誤。publicclassinstanceofTest{

publicstaticvoidmain(String[]args){

//聲明hello時(shí)使用Object類,則hello的編譯類型是Object

//Object是所有類的父類,但hello變量的實(shí)際類型是String

Objecthello="hello";

System.out.println((helloinstanceofObject));

//String和Object類存在繼承關(guān)系,可以進(jìn)展instanceof運(yùn)算,返回true

System.out.println((helloinstanceofString));

//Math和Object類存在繼承關(guān)系,可以進(jìn)展instanceof運(yùn)算,返回false

System.out.println((helloinstanceofMath));

//String實(shí)現(xiàn)了Comparabel接口,所以返回true

System.out.println((helloinstanceofComparable));

Stringa="hello";

//String類和Math類沒有繼承關(guān)系,所以下面的代碼編譯無法通過

//System.out.println((ainstanceofMath));

}

}4.8初始化塊:初始化塊是一段固定執(zhí)行的代碼,它不能承受任何參數(shù)。因此初始化塊對(duì)同一個(gè)類的所有對(duì)象所進(jìn)展的的初始化處理完全一樣。如果兩個(gè)構(gòu)造器中有相容的初始化代碼,且這些初始化代碼無須接收參數(shù),就可以把它們放在初始化塊中定義。當(dāng)創(chuàng)立java對(duì)象時(shí),系統(tǒng)總是先調(diào)用該類里定義的初始化塊,一樣類型的初始化塊之間按順序執(zhí)行。初始化塊在執(zhí)行構(gòu)造器之前執(zhí)行。與構(gòu)造器類型,創(chuàng)立一個(gè)java對(duì)象時(shí),不僅會(huì)執(zhí)行該類的普通初始化塊和構(gòu)造器,而且系統(tǒng)會(huì)一直上溯到j(luò)ava.lang.Object類,先執(zhí)行java.lang.Object類的初始化塊,再開場執(zhí)行java.lang.Object的構(gòu)造器,依次向下執(zhí)行其子類的初始化塊,再開場執(zhí)行其子類的構(gòu)造器…最后才執(zhí)行該類的初始化塊和構(gòu)造器,返回該類的對(duì)象。靜態(tài)初始化塊:如果定義初始化塊時(shí)使用了static修飾符,則這個(gè)初始化塊就變成了靜態(tài)初始化塊,也被稱為類初始化塊〔普通初始化塊負(fù)責(zé)對(duì)對(duì)象執(zhí)行初始化,類初始化塊則負(fù)責(zé)對(duì)類進(jìn)展初始化〕。靜態(tài)初始化塊總是類相關(guān)的,系統(tǒng)將在類初始化階段執(zhí)行靜態(tài)初始化塊,而不是在創(chuàng)立對(duì)象時(shí)才執(zhí)行。因此靜態(tài)初始化塊總是比普通初始化塊先執(zhí)行。通常靜態(tài)初始化塊用于對(duì)類變量執(zhí)行初始化處理。與普通初始化塊類型,系統(tǒng)在類初始化階段執(zhí)行靜態(tài)初始化塊時(shí),不僅會(huì)執(zhí)行本類的靜態(tài)初始化塊,而且還會(huì)一直上溯到j(luò)ava.lang.Object類,從最高父類開場一直到本類完畢,依次執(zhí)行每個(gè)類中的靜態(tài)初始化塊。publicclassTest{

publicstaticvoidmain(String[]args){

newLeaf();

newLeaf();

}

}

classRoot{

static{

System.out.println("Root的靜態(tài)初始化塊");

}

{

System.out.println("Root的初始化塊");

}

publicRoot(){

System.out.println("Root的無參構(gòu)造器");

}

}

classMidextendsRoot{

static{

System.out.println("Mid的靜態(tài)初始化塊");

}

{

System.out.println("Mid的初始化塊");

}

publicMid(){

System.out.println("Mid的無參構(gòu)造器");

}

publicMid(Stringmsg){

//通過this調(diào)用同一類中重載的構(gòu)造器

this();

System.out.println("Mid的帶有參數(shù)的構(gòu)造器");

}

}

classLeafextendsMid{

static{

System.out.println("Leaf的靜態(tài)初始化塊");

}

{

System.out.println("Leaf的初始化塊");

}

publicLeaf(){

super("abc");

System.out.println("執(zhí)行Leaf的構(gòu)造器");

}

}Root的靜態(tài)初始化塊Mid的靜態(tài)初始化塊Leaf的靜態(tài)初始化塊Root的初始化塊Root的無參構(gòu)造器Mid的初始化塊Mid的無參構(gòu)造器Mid的帶有參數(shù)的構(gòu)造器Leaf的初始化塊執(zhí)行Leaf的構(gòu)造器Root的初始化塊Root的無參構(gòu)造器Mid的初始化塊Mid的無參構(gòu)造器Mid的帶有參數(shù)的構(gòu)造器Leaf的初始化塊執(zhí)行Leaf的構(gòu)造器類初始化階段,先執(zhí)行最頂層父類的靜態(tài)初始化塊,然后依次向下,直到執(zhí)行當(dāng)前類的初始化塊。對(duì)象初始化階段,先執(zhí)行最頂層父類的初始化塊、最頂層父類的構(gòu)造器,然后依次向下,直到執(zhí)行當(dāng)前類的初始化塊、當(dāng)前類的構(gòu)造器Java系統(tǒng)加載并初始化某個(gè)類時(shí),總是保證該類的所有父類〔包括直接父類和間接父類〕全部加載并進(jìn)展初始化。靜態(tài)初始化塊和靜態(tài)成員變量的執(zhí)行順序與在源程序中排列順序一樣。第五章面向?qū)ο笙?.1java增強(qiáng)的包裝類為了解決8種基本類型的變量不能當(dāng)成Object類型變量使用的問題,java提供了包裝類的概念。除了int和char有點(diǎn)例外,其他的基本數(shù)據(jù)類型對(duì)應(yīng)的包裝類都是將其首字母大寫即可。自動(dòng)裝箱和自動(dòng)拆箱用法:publicclassAutoBoxingUnboxing{

publicstaticvoidmain(String[]args){

//直接把一個(gè)基本類型變量賦給Integer對(duì)象

IntegerinObj=5;

//直接把一個(gè)boolean類型變量賦給Object類型變量

ObjectboolObj=true;

//直接把一個(gè)Integer對(duì)象賦給int類型變量

intit=inObj;

if(boolObjinstanceofBoolean){

//先把Object對(duì)象強(qiáng)制類型轉(zhuǎn)換為Boolean類型,再賦給boolean變量

booleanb=(Boolean)boolObj;

System.out.println(b);

}

}

}包裝類還可實(shí)現(xiàn)基本類型變量和字符串之間的轉(zhuǎn)換。把字符串類型的值轉(zhuǎn)換為基本類型的值有兩種方式:利用包裝類提供的parseXxx(Strings)靜態(tài)方法利用包裝類提供的Xxx(Strings)構(gòu)造器String類提供了多個(gè)重載的valueOf()方法,用于將基本類型變量轉(zhuǎn)換成字符串。publicclassPrimitive2String{

publicstaticvoidmain(String[]args){

StringintStr="123";

//把一個(gè)特定的字符串轉(zhuǎn)換成int變量

intit1=Integer.parseInt(intStr);

intit2=newInteger(intStr);

System.out.println(it2);

StringfloatStr="4.56";

//把一個(gè)特定的字符串轉(zhuǎn)換成float變量

floatft1=Float.parseFloat(floatStr);

floatft2=newFloat(floatStr);

//把一個(gè)float變量轉(zhuǎn)換成String變量

StringftStr=String.valueOf(2.345f);

System.out.println(ftStr);

//把一個(gè)double變量轉(zhuǎn)換成String變量

StringdbStr=String.valueOf(3.344);

System.out.println(dbStr);

//把一個(gè)boolean變量轉(zhuǎn)換成String變量

StringboolStr=String.valueOf(true);

System.out.println(boolStr.toUpperCase());

}

}如果希望把基本類型變量轉(zhuǎn)換成字符串,還有一種更簡單的方法:將基本類型變量和〞〞進(jìn)展連接運(yùn)算,系統(tǒng)會(huì)自動(dòng)把基本類型變量轉(zhuǎn)換成字符串。雖然包裝類型的變量時(shí)引用數(shù)據(jù)類型,但包裝類的實(shí)例可以與數(shù)值類型的值進(jìn)展對(duì)比,這種對(duì)比是直接取出包裝類實(shí)例所包裝的數(shù)值來進(jìn)展對(duì)比的。publicclassTestDemo{

publicstaticvoidmain(String[]args){

Integera=newInteger(6);

System.out.println(a>5);

//兩個(gè)包裝類實(shí)例進(jìn)展對(duì)比時(shí),只有兩個(gè)包裝類引用指向同一個(gè)對(duì)象時(shí)才返回ture

System.out.println(newInteger(2)==newInteger(2));

}

}系統(tǒng)把一個(gè)-128-127之間的證書自動(dòng)裝箱成Integer實(shí)例,并放入了一個(gè)名為cache的數(shù)組中緩存起來。如果以后把一個(gè)-128-127之間的整數(shù)自動(dòng)裝箱成一個(gè)Integer實(shí)例時(shí),實(shí)際上是直接指向?qū)?yīng)的數(shù)組元素,因此-128-127之間的同一個(gè)整數(shù)自動(dòng)裝箱成Integer實(shí)例時(shí),永遠(yuǎn)都是引用cache數(shù)組的同一個(gè)數(shù)組元素,所以它們都相等。但如果整數(shù)不在這個(gè)范圍內(nèi),則會(huì)重新創(chuàng)立一個(gè)Integer實(shí)例。publicclassTestDmo2{

publicstaticvoidmain(String[]args){

Integera=2;

Integerb=2;

System.out.println(a==b);//true

Integerbiga=128;

Integerbigb=128;

System.out.println(biga==bigb);//false

}

}5.2處理對(duì)象對(duì)象打印的誤區(qū):publicclassPrintObject{

publicstaticvoidmain(String[]args){

Personp=newPerson("Peter");

//如果想打印p對(duì)象的內(nèi)容,下面兩種方法都不可以,打出來的都是地址值

//Object類提供的toString()方法總是返回該對(duì)象實(shí)現(xiàn)類的“類名+@+hashCode〞的值

System.out.println(p);

System.out.println(p.toString());

}

}

classPerson{

privateStringname;

publicPerson(Stringname){

=name;

}

}重寫toString〔〕方法,通過重寫,就可以讓系統(tǒng)在打印Apple對(duì)象時(shí)打印該對(duì)象的“自我描述〞內(nèi)容publicclassToStringTest{

publicstaticvoidmain(String[]args){

Applea=newApple("red",100);

//打印Apple對(duì)象

System.out.println(a);

}

}

classApple{

privateStringcolor;

privatedoubleweight;

//提供有參數(shù)的構(gòu)造器

publicApple(Stringcolor,doubleweight){

this.color=color;

this.weight=weight;

}

publicStringgetColor(){

returncolor;

}

publicvoidsetColor(Stringcolor){

this.color=color;

}

publicdoublegetWeight(){

returnweight;

}

publicvoidsetWeigth(doubleweigth){

this.weight=weight;

}

//重寫toString()方法

publicStringtoString(){

returncolor+","+weight;

}

}5.2.2==和equals方法Java中測試兩個(gè)變量是否相等有兩種方式,一種是利用==運(yùn)算符,一種是利用equals()方法。當(dāng)使用==來判斷兩個(gè)變量是否相等時(shí),如果兩個(gè)變量是基本類型變量,且都是數(shù)值類型〔不一定要求數(shù)據(jù)類型嚴(yán)格一樣〕,則只要兩個(gè)變量的值相等,就將返回true.對(duì)于兩個(gè)引用類型變量,只有他們指向同一個(gè)對(duì)象時(shí),==判斷才會(huì)返回true。==不可用于對(duì)比類型上沒有父子關(guān)系的兩個(gè)對(duì)象。publicclassEqualTest{

publicstaticvoidmain(String[]args){

intit=65;

floatfl=65.0f;

System.out.println("65和65.0是否相等"+(it==fl));//true

charch='A';

System.out.println("65和A是否相等"+(it==ch));//true

Stringstr1=newString("hello");

Stringstr2=newString("hello");

System.out.println("str1和str2是否相等"+(str1==str2));//false

System.out.println("str1是否equalsstr2?"+(str1.equals(str2)));//true

}

}當(dāng)Java程序直接使用形如〞hello〞的字符串直接量〔包括可以在編譯時(shí)就計(jì)算出來的字符串值〕時(shí),JVM將會(huì)使用常量池來管理這些字符串;當(dāng)使用newString〔"hello〞〕時(shí),JVM會(huì)先使用常量池來管理“hello〞直接量,再調(diào)用String類的構(gòu)造器來創(chuàng)立一個(gè)新的String對(duì)象,新創(chuàng)立的String對(duì)象被保存在堆內(nèi)存中。換句話說,newString〔“hello〞〕一共產(chǎn)生了兩個(gè)字符串對(duì)象。publicclassStringCompareTest{

publicstaticvoidmain(String[]args){

//s1直接引用常量池中的“瘋狂java〞

Strings1="瘋狂java";

Strings2="瘋狂";

Strings3="java";

//s4s5后面的字符串值可以在編譯時(shí)就確定下來,它們都直接引用常量池中的“瘋狂java〞

Strings4="瘋狂"+"java";

Strings5="瘋"+"狂"+"java";

//s6后面的字符串值不能在編譯時(shí)就確定下來

Strings6=s2+s3;

//s7引用堆內(nèi)存中新創(chuàng)立的String對(duì)象

Strings7=newString("瘋狂java");

System.out.println(s1==s4);//true

System.out.println(s1==s5);//true

System.out.println(s1==s6);//false

System.out.println(s1==s7);//false

}

}JVM常量池保證一樣的字符串直接量只有一個(gè),不會(huì)產(chǎn)生多個(gè)副本。String已經(jīng)重寫了Object的equals()方法,String的equals()方法判斷兩個(gè)字符串相等的標(biāo)準(zhǔn)是:只要兩個(gè)字符串所包含的字符序列一樣,通過equals()對(duì)比將返回true,否則返回false類成員不能訪問實(shí)例成員如果一個(gè)類始終只能創(chuàng)立一個(gè)實(shí)例,則這個(gè)類被稱為單例類publicclassSingletonTest{

publicstaticvoidmain(String[]args){

//創(chuàng)立Singleton對(duì)象不能通過構(gòu)造器,只能通過getInstance方法得到實(shí)例

Singletons1=Singleton.getInstance();

Singletons2=Singleton.getInstance();

System.out.println(s1==s2);

}

}

classSingleton{

//使用一個(gè)類變量來緩存曾經(jīng)創(chuàng)立的實(shí)例

privatestaticSingletoninstance;

//對(duì)構(gòu)造器使用private修飾,隱藏該構(gòu)造器

privateSingleton(){}

//提供一個(gè)靜態(tài)方法,用于返回Singleton實(shí)例

//該方法可以參加自定義控制,保證只產(chǎn)生一個(gè)Singleton對(duì)象

publicstaticSingletongetInstance(){

//如果Instance為Null,,則說明還不曾創(chuàng)立singleton對(duì)象

//如果intstance不為null,則說明已經(jīng)創(chuàng)立了Singleton對(duì)象,將不會(huì)重新創(chuàng)立新的實(shí)例

if(instance==null){

instance=newSingleton();

}

returninstance;

}5.4final修飾符Final修飾的變量不可被改變,一旦獲得了初始值,該final變量的值就不能被重新賦值。因此java語法規(guī)定:final修飾的成員變量必須由程序員顯式的指定初始值。Final修飾的類變量、實(shí)例變量能指定初始值的地方如下:類變量:必須在靜態(tài)初始化塊中指定初始值或聲明該類型變量時(shí)指定初始值,而且只能在兩個(gè)地方的其中之一指定實(shí)例變量:必須在非靜態(tài)初始化塊、聲明該實(shí)例變量或構(gòu)造器中指定初始值,而且只能在三個(gè)地方的其中之一指定。實(shí)例變量不能在靜態(tài)初始化塊中指定初始值,因?yàn)殪o態(tài)初始化塊時(shí)靜態(tài)成員,不可訪問實(shí)例變量——非靜態(tài)成員;類變量不能在普通初始化塊中指定初始值,因?yàn)轭愖兞吭陬惓跏蓟A段已經(jīng)被初始化了,普通初始化塊不能對(duì)其重新賦值。publicclassFinalVariableTest{

//定義成員變量時(shí)指定默認(rèn)值,合法

finalinta=6;

//下面這三個(gè)變量將在構(gòu)造器或初始化塊中指定初始值

finalStringstr;

finalintc;

finalstaticdoubled;

//ch既沒有指定默認(rèn)值,有沒有在初始化塊、構(gòu)造器中指定初始值

//finalcharch;

//初始化塊,對(duì)沒有指定默認(rèn)值的實(shí)例變量指定初始值

{

//在初始化塊中為實(shí)例變量指定初始值,合法

str="hello";

//定義a實(shí)例變量時(shí),已經(jīng)指定了默認(rèn)值,不能重新為a賦值

//a=9;

}

static{

//在靜態(tài)初始化塊中為類變量指定初始值,合法

d=5.6;

}

publicFinalVariableTest(){

//str在初始化塊中已定義初始值,不可重新賦值

//str="java";

//構(gòu)造器,可對(duì)既沒有指定默認(rèn)值,又沒有在初始化塊中指定初始值的實(shí)例變量指定初始值

c=5;

}

publicvoidchangeFinal(){

//普通方法不能為final修飾的成員變量賦值

//d=1.2;

//不能在普通方法中為final成員變量指定初始值

//ch='a';

}

publicstaticvoidmain(String[]args){

FinalVariableTestft=newFinalVariableTest();

System.out.println(ft.a);

System.out.println(ft.c);

System.out.println(ft.d);

}

}Final局部變量系統(tǒng)不會(huì)對(duì)局部變量進(jìn)展初始化,局部變量必須由程序員顯式初始化。因此final修飾局部變量時(shí),既可以在定義時(shí)指定默認(rèn)值,也可以不指定默認(rèn)值。如果final修飾的局部變量在定義時(shí)沒有指定默認(rèn)值,則可以在后面代碼中對(duì)該final變量賦初始值,但只能一次,不能重復(fù)賦值。當(dāng)使用final修飾基本類型變量時(shí),不能對(duì)基本類型變量重新賦值,因此基本列表變量不能改變。但對(duì)于引用類型變量而言,它保存的僅僅是一個(gè)引用,final只保證這個(gè)引用類型變量所引用的地址不會(huì)改變,即一直引用同一個(gè)對(duì)象,但這個(gè)對(duì)象完全可以改變。publicclassFinalReferenceTest{

publicstaticvoidmain(String[]args){

//final修飾數(shù)組變量,iArr是一個(gè)引用變量

finalint[]iArr={5,6,12,9};

System.out.println(Arrays.toString(iArr));

//對(duì)數(shù)組元素排序,合法

Arrays.sort(iArr);

System.out.println(Arrays.toString(iArr));

//對(duì)數(shù)組元素賦值,合法

iArr[2]=-8;

System.out.println(Arrays.toString(iArr));

//對(duì)iArr重新賦值,非法

//iArr=null;

//final修飾Person變量,p是一個(gè)引用變量

finalPersonp=newPerson(45);

//改變p對(duì)象的age實(shí)例變量,合法

p.setAge(23);

System.out.println(p.getAge());

//對(duì)p重新賦值,非法

//p=null;

}

}

classPerson{

privateintage;

publicPerson(){}

//有參數(shù)的構(gòu)造器

publicPerson(intage){

this.age=age;

}

publicvoidsetAge(intage){

this.age=age;

}

publicintgetAge(){

returnage;

}

}可執(zhí)行“宏替換〞的final變量對(duì)于一個(gè)final變量來說,不管它是類變量、實(shí)例變量,還是局部變量,只要該變量滿足三個(gè)條件,這個(gè)final變量就不再是一個(gè)變量,而是相當(dāng)于一個(gè)直接量使用final修飾符修飾在定義該final變量時(shí)指定了初始值該初始值可以在編譯時(shí)就被確定下來如果被賦的表達(dá)式只是基本的算術(shù)表達(dá)式或字符串連接運(yùn)算,沒有訪問普通變量,調(diào)用方法,java編譯器同樣會(huì)將這種final變量當(dāng)成“宏變量〞處理。publicclassFinalReplaceTest{

publicstaticvoidmain(String[]args){

//下面定義了4個(gè)final宏變量,因?yàn)榫幾g器在編譯時(shí)就可以確定

finalinta=5+2;

finaldoubleb=1.2/3;

finalStringstr="瘋狂"+"java";

finalStringbook="瘋狂java講義:"+99.0;

//下面的book2變量的值因?yàn)檎{(diào)用了方法,所以無法在編譯時(shí)被確定下來

finalStringbook2="瘋狂java講義:"+String.valueOf(99.0);

System.out.println(book=="瘋狂Java講義:99.0");//相等

System.out.println(book2=="瘋狂java講義:99.0");//不相等

}

}Java會(huì)使用常量池來管理曾經(jīng)用過的字符串直接量,例如執(zhí)行Stringa=〞java〞,語句之后,常量池中就會(huì)緩存一個(gè)字符串“Java〞;如果程序再執(zhí)行Stringb=〞java〞,系統(tǒng)將會(huì)讓b直接指向常量池中的“java〞字符串,因此a==b將會(huì)返回true.publicclassStringJoinTest{

publicstaticvoidmain(String[]args){

Strings1="瘋狂java";

//s2變量引用的字符串可以在編譯時(shí)就確定下來,因此s2的直接引用常量池中已有的“瘋狂java"字符串

Strings2="瘋狂"+"java";

System.out.println(s1==s2);

Stringstr1="瘋狂";

Stringstr2="java";

//str3由str1和str2進(jìn)展連接運(yùn)算后得到的。由于str1和str2只是兩個(gè)普通變量,編譯器不會(huì)執(zhí)行“宏替換〞,因而不能在

//編譯時(shí)確定s3的值,也就無法讓s3指定字符串池中緩存的“瘋狂Java〞

Strings3=str1+str2;

System.out.println(s1==s3);

//只要讓編譯器對(duì)str1和str2兩個(gè)變量執(zhí)行“宏替換〞,這樣編譯器即可在編譯階段就確定s3的值,就會(huì)讓s3指向字符串池

//中緩存的“瘋狂java〞。也就是,只要將str1和str2使用final修飾即可

}

}Final方法Final修飾的方法不可被重寫,但是可以重載Final類Final修飾的類不可以有子類。因而為了保證某個(gè)類不可被繼承,則可以使用final修飾這個(gè)類。5.5抽象類抽象方法和抽象類必須使用abstract修飾符來定義,有抽象方法的類只能被定義成抽象類,抽象類里可以沒有抽象方法。抽象方法和抽象類的規(guī)則如下:抽象類必須使用abstract修飾符來修飾,抽象方法也必須使用abstract修飾符來修飾,抽象方法不能有方法體。抽象類不能被實(shí)例化,無法使用new關(guān)鍵字來調(diào)用抽象類的構(gòu)造器創(chuàng)立抽象類的實(shí)例。即使抽象類里不包含抽象方法,這個(gè)抽象類也不能創(chuàng)立實(shí)例。抽象類可以包含成員變量、方法〔普通方法和抽象方法都可以〕、構(gòu)造器、初始化塊、內(nèi)部類〔接口、枚舉〕5種成分。抽象類的構(gòu)造器不能用于創(chuàng)立實(shí)例,主要是用于被其他子類調(diào)用。含有抽象方法的類〔包括直接定義了一個(gè)抽象方法;或繼承了一個(gè)抽象父類,但沒有完全實(shí)現(xiàn)父類包含的抽象方法;或?qū)崿F(xiàn)了一個(gè)接口,但沒有完全實(shí)現(xiàn)接口包含的抽象方法三種情況〕只能被定義成抽象類。抽象類:多了一個(gè)能力,抽象類可以包含抽象方法;失去了一個(gè)能力,抽象類不能用于創(chuàng)立實(shí)例。定義抽象方法只需在普通方法上增加abstract修飾符,并把普通方法的方法體〔也就是方法后花括號(hào)括起來的局部〕全部去掉,并在方法后增加分號(hào)即可。定義抽象類只需在普通類上增加abstract修飾符即可。/**

*CreatedbyAIwenon2017/5/19.

*/

publicabstractclassShape{

{

System.out.println("執(zhí)行shape的初始化塊...");

}

privateStringcolor;

//定義一個(gè)計(jì)算周長的抽象方法

publicabstractdoublecalPe

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論