版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
CreatedbyAlwenon2023/5/14.
java是面對對象的程序設計語言;類可被認為是一種自定義的數(shù)據類型,可以運用類來定義變量,全部運用類定義的
變量都是引用變量,它們將會引用到類的對象。類用于描述客觀世界里某一類對象的共同特征,而對象則是類的具體
存在,java程序運用類的構造器來創(chuàng)建該類的對象。
java也支持面對對象的三大特征:封裝、繼承、和多態(tài)。java供應了private、protected、和public三個訪問限制
修飾符來實現(xiàn)良好的封裝,供應了extends關鍵字讓子類繼承父類,子類繼承父類就可以繼承到父類的成員變量和和
方法,假如訪問限制允許,子類實例可以干脆調用父類里定義的方法。繼承是實現(xiàn)類復用的重要手段。運用繼承關系
來實現(xiàn)復用時,子類對象可以干脆賦給父類變量,這個變量具有多態(tài)性。
面對對象的程序設計過程中有兩個重要的概念:類(Class)和對象(object,也被稱為實例,instance)。類可以包
含三種最常見的成員:構造器、成員變量、和方法。
構造器用于構造該類的實例,java語言通過new關鍵字類調用構造器,從而返回該類的實例。構造器是一個類創(chuàng)建對
象的根本途徑,假如一個類沒有構造器,這個類通常無法創(chuàng)建實例。因此java語言供應了一個功能:假如程序員沒有
為一個類編寫構造器,則系統(tǒng)會為該類供應一個默認的構造器,這個構造器總是沒有參數(shù)的。一旦程序員為一個類供
應了構造器,系統(tǒng)將不再為該類供應構造器。
構造器用于對類實例進行初始化操作,構造器支持重載,假如多個重載的構造器里包含了相同的初始化代碼,則可以
把這些初始化代碼放置在一般初始化塊里完成,初始化塊總在構造器執(zhí)行之前被調用。靜態(tài)初始化塊代碼用于初始化
類,在類初始化階段被執(zhí)行。假如繼承樹里某一個類須要被初始化時,系統(tǒng)將會同時初始化該類的全部父類。
構造器修飾符:可以是public、protected,private其中之一,或者省略構造器名:構造器名必需和類名相同。
留意:構造器既不能定義返回值類型,也不能運用void聲明構造器沒有返回值。假如為構造器定義了返回值類型,或
運用void聲明構造器沒有返回值,編譯時不會出錯,但java會把這個所謂的構造器當成方法來處理——它就不再是
構造器。
事實上類的構造器是有返回值的,當運用new關鍵字來調用構造器時,構造器返回該類的實例,可以把這個類的實例
當成構造器的返回值。因此構造器的返回值類型總是當前類,無須定義返回值類型。不要在構造器里顯式的運用return
來返回當前類的對象,因為構造器的返回值是隱式的。
java類名必需是由一個或多個有意義的單詞連綴而成的,每個單詞首字母大寫,其他字母全部小寫,單詞與單詞之間
不要運用任何分隔符。
成員變量:
成員變量的修飾符:public、protected、private、static、final前三個只能出現(xiàn)一個再和后
面的修飾符組合起來修飾成員變量,也可省略。
成員變量:由一個或者多個有意義的單詞連綴而成,第一個單詞首字母小寫,后面每個單詞首
字母大寫,其他字母全部小寫,單詞與單詞之間不要運用任何分隔符。
類型:可以是java語言允許的任何數(shù)據類型,包括基本類型和引用類型。
成員方法:
方法修飾符:public、protected',private、static、final、abstract,前三個只能出現(xiàn)一個,
static和final最多只能出現(xiàn)其中的一個,和abstract組合起來運用。也可省略。
返回值類型:可以是java語言的允許的任何數(shù)據類型,包括基本類型和引用類型。
方法名:和成員變量的方法命名規(guī)則相同,通常建議方法名以英文動詞開頭。
方法體里多條可執(zhí)行語句之間有嚴格的執(zhí)行依次,排在方法體前面的語句總先執(zhí)行,排在方法
體后面的語句總是后執(zhí)行。
static是一個特殊的關鍵字,它可用于修飾方法、成員變量等成員。static修飾的成員表明它屬
于這個類本身,而不屬于該類的單個實例,因此通過把static修飾的成員變量和方法被稱為類
變量、類方法(靜態(tài)成員變量,靜態(tài)成員方法);不運用static修飾的成員變量和方法稱為實
例變量和實例方法(非靜態(tài)成員變量,非靜態(tài)成員方法)。靜態(tài)成員不能干脆訪問非靜態(tài)成員。
static的真正作用就是用于區(qū)分成員變量、方法、內部類、初始化塊,這四種成員原委屬于類
本身還是屬于實例。有static修飾的成員屬于類本身,沒有類修飾的成員屬于該類的實例。
java類大致有如下作用:
定義變量
創(chuàng)建對象
調用類的類方法或訪問類的類變量。
定義一個類就是為了重復創(chuàng)建該類的實例,同一個類的多個實例具有相同的特征,而類則是定
義了多個實例的共同特征。
類里定義的方法和成員變量都可以通過類或實例來調用。Static修飾的方法和成員變量,既可
通過類來調用,也可通過實例來調用;沒有運用static修飾的一般方法成員變量,只可通過實
例來調用。
Personp=newPerson。;這行代碼創(chuàng)建了一個Person實例,也被稱為Person對象,這個
Person對象被賦給p變量。在這行代碼中事實上產生了兩個東西,一個是p變量,一個是Person
對象。P引用變量本身只存儲了一個地址值,并未包含任何實際數(shù)據,但它指向實際的Person
對象。
Person對象由多塊內存組成,不同內存塊分別存儲了Person對象的不同成員變量。類是一種
引用數(shù)據類型,因此程序中定義的Person類型的變量事實上是一個引用,它被存放在棧內存里,
指向實際的Person對象;而真正的Person對象則存放在堆內存中。
當一個對象被創(chuàng)建成功以后,這個對象將保存在堆內存中,java程序不允許干脆訪問堆內存中
的對象,只能通過該對象的引用操作該對象。堆內存里的對象可以有多個引用,即多個引用變
量指向同一個對象。
假如堆內存里的對象沒有任何變量指向該對象,那么程序將無法再訪問該對象,這個對象也就
變成了垃圾,java垃圾回收機制將回收該對象,釋放該對象所占的內存區(qū)。
對象的this引用
Java供應了一個this關鍵字,this關鍵字總是指向調用該方法的對象。This作為對象的默認
引用有兩種情形:
構造器中引用該構造器正在初始化的對象;在方法中引用調用該方法的對象。
This關鍵字最大的作用就是讓類中一個方法,訪問該類里的另一個方法或者實例變量。
Java允許對象的一個成員干脆調用另一個成員,可以省略this前綴。
假如在static修飾的方法中運用this關鍵字,則這個關鍵字就無法指向合適的對象,所以,static
修飾的方法中不能運用this引用。
Java編程時不要運用對象去調用static修飾的成員變量、方法、而是應當運用類去調用static
修飾的成員變量、方法。
假如的確須要在靜態(tài)方法中訪問另一個一般方法,則只能重新創(chuàng)建一個對象。
大部分的時候,一般方法訪問其他方法、成員變量時無須運用this前綴,但假如方法里有個局
部變量和成員變量同名,但程序又須要在該方法里訪問這個被覆蓋的成員變量,則必需運用this
前綴。
This引用也可以用于構造器中作為默認引用,由于構造器時干脆運用new關鍵字來調用,而不
是運用對象來調用的,所以this在構造器中代表該構造器正在初始化對象。
方法:
Java里的方法不能獨立存在,全部的方法都必需定義在類里。假如這個方法是用來static修飾,
則這個方法屬于這個類,否則這個方法屬于這個類的實例。執(zhí)行方法時,必需運用類或者對象
作為調用者。同一個類的一個方法調用另外一個方法時,假如被調方法是一般方法,則默認運
用this作為調用者;假如被調用方法是靜態(tài)方法,則默認運用類作為調用者。也就是說java
中看起來某些方法可以被獨立執(zhí)行,但事實上還是運用this或者類來作為調用者。
Java里方法參數(shù)傳遞方式只有一種:值傳遞。所謂值傳遞,就是講實際參數(shù)值的副本(復制品)
傳入方法內,而參數(shù)本身不會受到任何影響。
從JDK1.5之后,java允許定義形參個數(shù)可變的參數(shù),從而允許為方法指定數(shù)量不確定的形參。
假如在定義方法時,在最終一個形參的類型后增加三點(…),則表明該形參可以接受多個參數(shù)
值,多個參數(shù)值被當成數(shù)組傳入。
publicclassVarargs{
//定義形參可變的方法
publicstaticvoidtest(inta,String...books){
//books被當成數(shù)組處理
for(Stringtmp:books){
System,outprintln(tmp);
)
System,outprintln(a);
)
publicstaticvoidmain(String[]args){
//調用test方法
^es45,"hello","world","aa");
)
數(shù)組形式的形參可以處于形參列表的隨意位置,但個數(shù)可變的形參只能處于形參表的最終。也
就是說最多只能有一個長度可變的形參。
形參可變和傳入數(shù)組的區(qū)分:
publicstaticvoidtest(inta,String...books);
publicstaticvoidtest(inta,String口books);
test(5,"aa","bb","cc");
test(5,newString[]{"aa","bb","cc"});
方法重載:
Java允許同一個類里定義多個同名方法,只要形參列表不同就行。假猶如一個類中包含了兩個
或兩個以上方法的方法名相同,但形參列表不同,則被稱為方法的重載。
Java程序確定一個方法須要三個要素:調用者;方法名;形參列表。
方法的重載要求就是兩同一不同:同一個類中方法名相同,參數(shù)列表不同。至于方法的其他部
分,如方法返回值類型、修飾符等,與方法重載沒有任何關系。
publicclassOverloadVarargs{
publicvoidtest(Stringmsg){
System.outprintin("只有一個參數(shù)的test");
}
//因為前面已經有了一個字符串參數(shù)的方法,則長度可變形參里不包含一個字符串參數(shù)的
形式
publicvoidtest(String...books){
System.outprintin("形參可變的test方法叱
)
publicstaticvoidmain(String[]args){
OverloadVarargsolv=newOverloadVarargs();
//下面兩次調用將執(zhí)行其次個test方法
olv.testO;
olv.test("aa","bb");
//將調用第一個test方法
olv.test("aa");
〃將調用其次個test方法
olv.test(newString[]{"aa"});
Java中變量分為:成員變量和局部變量。成員變量被分為類變量和實例變量兩種,定義成員變
量時沒有static修飾的就是實例變量,有static修飾的就是類變量。
?變量的命名:從程序的可讀性角度來看,應當是多個有意義的單詞連綴而成,其中第一個單
詞首字母小寫,后面每個單詞首字母大寫。
?假如通過一個實例修改了類變量的值,由于這個類變量并不屬于它,而是屬于它對應的類。
因此,修改的照舊是類變量,與通過該類來修改類變量的結果完全相同,這會導致該類的其
他實例來訪問這個類變量時也將獲得這個被修改過的值。
?成員變量無須顯式初始化,只要為一個類定義了類變量或實例變量,系統(tǒng)就會在這個類的初
始化階段或創(chuàng)建該類的實例時,進行默認初始化。
?實例變量隨實例的存在而存在,而類變量則隨類的存在而存在。實例也可訪問類變量,同一
個類的全部實例訪問類變量時,事實上訪問的是該類本身的同一個變量,也就是說,訪問了
同一片內存區(qū)。
?局部變量依據定義形式的不同,又可分為三種形式:形參,方法局部變量,代碼塊局部變量;
局部變量除了形參之外,都必需顯示初始化。
?在同一個類里,成員變量的作用范圍是整個類內有效,一個類里不能定義兩個同名的成員變
量,即使一個是類變量,一個是實例變量也不行;一個方法里不能定義兩個同名的方法局部
變量,方法局部變量與形參也不能同名;同一個方法中不同代碼塊內局部變量可以同名;假
如先定義代碼塊局部變量,后定義方法局部變量,前面定義的代碼塊局部變量與后面定義的
方法局部變量也可同名.
?Java允許局部變量和成員變量同名,假如方法里的局部變量和成員變量同名,局部變量會
覆蓋成員變量,假如須要在這個方法里引用被覆蓋的成員變量,則可運用this(對于實例變
量)或類名(對于類變量)作為調用者來限定訪問成員變量。
publicclassVariableOverrideTest{
//定個name實例變量
privateStringname="李剛";
//定義一個price類變量
privatestaticdoubleprzce=78.0;
publicstaticvoidmain(String[]args){
〃方法里局部變量覆蓋成員變量,將輸出price的局部變量65
intprice=65;
System,out.println(price);
〃運用類名作為price變量的限定,將輸出price類變量的值
System.outprintln(VariableOverrideTest.p/7c<^;
newVariableOverrideTestO.infoO;
)
publicvoidinfo(){
//方法里的局部變量,局部變量覆蓋成員變量,輸出name局部變量的值:孫悟空
Stringname="孫梧空";
System,otztprintln(name);
//將輸出name實例的值:李剛
System,out.println(this.name);
)
}
當系統(tǒng)加載類或創(chuàng)建該類的實例時,系統(tǒng)自動為成員變量支配內存空間,并在支配內存空間后,
自動為成員變量指定初始值。
Personp1=newPersonf);,假如這行代碼是第一次運用Person類,則系統(tǒng)通常會在第一次
運用Person類時加載這個類,并初始化這個類。
局部變量定以后,必需經過顯式初始化后才能運用,系統(tǒng)不會為局部變量執(zhí)行初始化。局部變
量不屬于任何類或者實例,因此它總是保存在其所在方法的棧內存中。假如局部變量時基本類
型的變量,則干脆把這個變量的值保存在該變量對應的內存中;假如局部變量是一個引用類型
的變量,則這個變量里存放的是地址,通過該地址引用到該變量實際引用的對象或者數(shù)組。
棧內存中的變量無須系統(tǒng)垃圾回收,往往隨是方法或代碼塊的運行結束而結束。
假如定義的某個變量是用于描述某個類或某個對象的固有信息的,這種變量應當定義成成員變
量。假如這種信息對這個類的全部實例完全相同,或者說它是類相關的,則該定義成類變量;
假如這個信息是實例相關的,則應當定義成實例變量。
用于保存某個類或某個實例狀態(tài)信息的變量通常應當運用成員變量。假如某個信息須要在某個
類的多個方法之間進行共享,則這個信息應當運用成員變量來保存。
隱藏和封裝
訪問限制符用于限制一個類的成員是否可以被其他類訪問。
Java供應了3個訪問限制修飾符:private,protected,和public,還有一個默認訪問限制修
飾符default
Private(當前類訪問權限);default(包訪問權限);protected(子類訪問權限):假如一個成
員運用protected訪問修飾符修飾,那么這個成員既可以被同一個包中的其他類訪問,也可以
被不同包中子類訪問。通常狀況下,運用protected修飾的方法,通常希望其子類來重寫這個
方法。PubHc(公共訪問權限)
對于局部變量而言,其作用域就是它所在的方法,不行能被其他類訪問,因此不能運用訪問限
制符來修飾。
外部類只能有兩種訪問限制級別:public和默認,不能運用private和protected
publicclassPerson{
privateStringname;
privateintage;
publicvoidsetName(Stringname){
if(name.length()>61|name.length()<2){
System.outprintln("error");
return;
)
else{
=name;
)
}
publicStringgetName(){
return;
)
publicvoidsetAge(intage){
if(age>100||age<0){
System.outprintln("error");
}else{
this,age=age;
)
)
publicintgetAge(){
returnthis.age;
)
}
publicclassPersonTest{
publicstaticvoidmain(String[]args){
Personp=newPersonQ;
//下面的變量不會運行錯誤,但是會提示錯誤
p.setAge(lOOO);
//因為上面沒有成功設置P的age成員,故輸出0
System.outprintln(p.getAge());
//成功設置P的age成員
p.setAge(30);
System,outprintin(p.getAge());
//成功設置P的name成員
p.setName("李剛叱
System.OLztprintln(p.getName());
)
構造器:
構造器最大的用途是創(chuàng)建對象時執(zhí)行初始化。當創(chuàng)建一個對象時,系統(tǒng)為這個對象的實例變量
進行默認初始化,這種默認的初始化把全部基本類型的實例變量設為0(對數(shù)值型實例變量)或
false(對布爾型實例變量),把全部引用類型的實例變量設為nullo假如想變更這種默認的初
始化,想讓系統(tǒng)創(chuàng)建對象時就位該對象的實例變量顯式指定初始值,就可以通過構造器來實現(xiàn)。
因為構造器主要用于被其他方法調用,用以返回該類的實例,因而通常把構造器設置成public
訪問權限,從而允許系統(tǒng)中任何位置的類來創(chuàng)建該類的對象。假如設置成protected,主要用于
被子類調用;設置為private,阻擋其他類創(chuàng)建該類的實例。
假如系統(tǒng)中包含了多個構造器,其中一個構造器B的執(zhí)行體里完全包含另一個構造器A的執(zhí)行
體。為了這構造器B中調用構造器A中的初始化代碼,又不會重新創(chuàng)建一個java對象,可以
運用this關鍵字來調用相應的構造器。
publicclassApple{
publicStringname;
publicStringcolor;
publicdoubleweight;
〃兩個參數(shù)的構造器
publicApple(Stringname,Stringcolor){
=name;
this.color=color;
}
〃三個參數(shù)的構造器
publicApple(Stringname,Stringcolor,doubleweight){
//通過this調用另一個重載的構造器的初始化代碼
this(name,color);
//通過this引用該構造器正在初始化的Java對象
this.weight=weight;
)
運用this調用另一個重載的構造器只能在構造器中運用,而且必需作為構造器執(zhí)行體的第一條
語句。運用this調用重載的構造器時,系統(tǒng)會依據this后括號里的實參來調用形參列表與之對
應的構造器
類的繼承:
Java繼承通過extends關鍵字來實現(xiàn)實現(xiàn)繼承的類被稱為子類,被繼承的類被稱為父類,有的
也稱為基類、超類。
因為子類是一種特殊的父類,因此父類包含的范圍總比子類包含的范圍要大。
Java子類不能獲得父類的構造器
publicclassFruit{
publicdoubleweight;
publicvoidinfo(){
System,outprintln(weight);
)
publicclassAppleextendsFruit{//Apple類繼承了Fruit類,所以Apple對象也
就有了weight成員變量和info。方法
publicstaticvoidmain(String[]args){
Applea=newApple();
//Apple對象本身沒有weight成員變量,但是,Apple父類有weight成員變量,所
以,也可以訪問Apple對象的weight成員變量
a.weight=56;
//調用Apple對象的info()方法
O;
)
Java類只能有一個干脆父類,事實上,Java類可以有無限多個間接父類。
重寫父類方法:
子類擴展了父類,子類是一個特殊的父類。大部分時候,子類總是以父類為基礎,額外增加新
的成員變量和方法。但有一種狀況例外:子類須要重寫父類方法。
publicclassBird{
//Bird類的fly。方法
publicvoidfly(){
System,outprintin("我在天空中飛");
)
)
publicclassOstrichextendsBird{
//重寫B(tài)ird類的fly()方法
publicvoidfly(){
System.outprinting我在陸地上飛”);
)
publicstaticvoidmain(String[]args){
//創(chuàng)建Ostrich對象
Ostrichor=newOstrich();
〃執(zhí)行Ostrich對象的fly()方法,將輸出“我在陸地上飛”
or.flyQ;
)
}
這種子類包含與父類同名方法的現(xiàn)象被稱為方法重寫(Override),也被稱為方法覆蓋。可以說
子類重寫了父類的方法,也可以說子類覆蓋了父類的方法。
方法的重寫要遵循“兩同兩小一大”規(guī)則,“兩同”即方法名相同、形參列表相同;“兩小”指
的是子類方法的返回值類型應比父類方法返回值類型更小或相等,子類方法聲明拋出的異樣類
應比父類聲明拋出的異樣類更小或相等;“一大”指的是子類方法的訪問權限應比父類方法的訪
問權限更大或相等。
覆蓋方法和被覆蓋方法要么都是類方法,要么都是實例方法。
當子類覆蓋了父類方法后,子類的對象將無法訪問父類中被覆蓋的方法,但可以在子類方法中
調用被覆蓋的方法。假如須要在子類方法中調用父類中被覆蓋的方法,則可以運用super(被
覆蓋的是實例方法)或者父類類名(被覆蓋的是類方法)作為調用者來調用父類中被覆蓋的方
法。
假如父類方法具有private訪問權限,則該方法對其子類是障藏的,因此其子類無法訪問該方法,
也就是無法重寫該方法。
重載只要發(fā)生在同個類多個同名方法之間,而重寫發(fā)生在子類和父類同名方法之間。父類方法
和子類方法之間也可能發(fā)生重載。
Super限定:
Super是Java供應的一個關鍵字,super用于限定該對象調用它從父類繼承得到的實例變量
或方法。Super不能出現(xiàn)在static修飾的方法中。Static修飾的方法是屬于類的,該方法的調
用者可能是一個類,而不是對象,因而super限定就失去了意義。
假如在構造器中運用super,則super用于限定該構造器初始化的是該對象從父類繼承得到的實
例變量,而不是該類自己定義的實例變量。
假如子類定義了和父類同名的實例變量,則會發(fā)生子類實例變量隱藏父類實例變量的情形。在
正常狀況下,子類里定義的方法干脆訪問該實例變量,默認會訪問到子類中定義的實例變量,
無法訪問到父類中被隱藏的實例變量。在子類定義的實例方法中可以通過super來訪問父類中
被隱藏的實例變量。
publicclassBaseClass{
publicinta=5;
}
publicclassSubClassextendsBaseClass{
publicinta=7;
publicvoidaccessOwner(){
System,outprintlnfa);
}
publicvoidaccessBase(){
//通過super來限定訪問從父類繼承得到的a實例變量
System,out.println(super.a);
)
publicstaticvoidmain(String[]args){
SubClasssb=newSubClassO;
sb.accessBase();〃輸出5
sb.accessOwner。;〃輸出7
)
}
假如在某個方法中訪問名為a的成員變量,但沒有顯式指定調用者,則系統(tǒng)查找a的依次為:
1.查找該方法中是否出名為a的局部變量
2.查找當前類中是否包含名為a的成員變量
3.查找a的干脆父類中是否包含名為a的成員變量,一次上溯a的全部父類,直到
java.lang.Object類,假如最終不能找到名為a的成員變量,則系統(tǒng)出現(xiàn)編譯錯誤。
假如被覆蓋的是類變量,在子類的方法中則可以通過父類名作為調用者來訪問被覆蓋的類變量
當程序創(chuàng)建一個子類對象時,系統(tǒng)不僅會為該類中定義的實例變量支配內存,也會為它從父類
繼承得到的全部實例變量支配內存,即使子類定義了與父類中同名的實例變量。
假如在子類里定義了與父類中已有變量同名的變量,那么子類中定義的變量會隱藏父類中定義
的變量。留意不是完全覆蓋,因此系統(tǒng)在創(chuàng)建子類對象時,照舊會為父類中定義的、被障藏的
變量支配內存空間。
publicclassParent{
publicStringtag="helloworld";
)
publicclassDerivedextendsParent{
//定義一個私有的tag實例變量來隱藏父類的tag實例變量
privateStringtag="abc";
)
publicclassHideTest{
publicstaticvoidmain(String[]args){
Derivedd=newDerived();
//程序不行訪問d的私有變量tag,所以會出現(xiàn)編譯錯誤
//System,out.printlnfd.tag);
〃將d變量顯式的向上轉型為Parent后,即可訪問tag實例變量
System,outprintln(((Parent)d).tag);
)
)
調用父類構造器:
子類不會獲得父類的構造器,但子類構造器里可以調用父類構造器的初始化代碼。在一個構造
器里調用另一個重載的構造器運用this調用來完成,在子類構造器中調用父類構造器運用
super調用來完成。
publicclassBase{
publicdoublesize;
publicStringname;
publicBase(doublesize,Stringname){
this.size=size;
=name;
}
}
publicclassSubextendsBase{
publicStringcolor;
publicSub(doublesize,Stringname,Stringcolor){
//通過super調用父類構造器的初始化過程
super(size,name);
th運.color=color;
)
publicstaticvoidmain(String[]args){
Subs=newSub(5.6,"測試","red");
System,outprintln(s.size+",,,+s.naine+","+s.color);
)
)
Super調用的是其父類的構造器,而this調用的是同一個類中重載的構造器;因此,運用super
調用父類的構造器也必需出現(xiàn)在子類構造器執(zhí)行體的第一行,所以this調用和super調用不會
同時出現(xiàn)。
當調用子類構造器來初始化子類對象時,父類構造器總會在子類構造器之前執(zhí)行;不僅如此,
執(zhí)行父類構造器時,系統(tǒng)會再次上溯執(zhí)行其父類的構造器……依次類推,創(chuàng)建任何java對象,
最先執(zhí)行的總是java.lang.Object類的構造器。
publicclassCreature{
publicCreature(){
System,outprinting無參");
}
}
publicclassAnimalextendsCreature{
publicAnimal(Stringname){
System.outprintln("Animal帶一個參數(shù)的構造器"+name);
)
publicAmmal(Stringname,intage){
//this調用同一個重載構造器
this(name);
System.outprintln("Aninial帶兩個參數(shù)的構造器"+age);
)
}
publicclassWolfextendsAnimal{
publicWolf(){
super("灰太狼",4);
System.outprintln("wolf無參構造器叱
)
publicstaticvoidmain(String[]args){
Wolfwf=newWolf();
〃雖然main方法只創(chuàng)建了一個Wolf對象,但系統(tǒng)在底層完成了困難的操作,運行將
會得到
//無參
//Animal帶一個參數(shù)的構造器灰太狼
//Animal帶兩個參數(shù)的構造器4
//wolf無參構造器
}
}
創(chuàng)建任何對象總是從該類所在繼承樹最頂層類的構造器起先執(zhí)行,然后依次向下執(zhí)行,最終才
執(zhí)行本類的構造器。假如某個父類通過this調用了同類中重載的構造器,就會依次執(zhí)行此父類
的多個構造器。
4.7多態(tài):
Java引用變量有兩個類型:一個是編譯時類型,一個是運行時類型。編譯時類型由聲明該變量
時運用的類型確定,運行時類型由實際賦給該變量的對象確定。假如編譯時類型和運行時類型
不一樣,就可能出現(xiàn)所謂的多態(tài)。
publicclassBaseClass{
publicintbook=6;
publicvoidbase(){
System.outprintln("父類的一般方法叱
)
publicvoidtest(){
System.outprinting父類被覆蓋的方法");
)
)
publicclassSubClassextendsBaseClass{
//重寫定義一個book實例變量隱藏父類的book實例變量
publicStringbook="abc";
publicvoidtest(){
5丫$16111."重1±11111("子類的覆蓋父類的方法");
)
publicvoidsub(){
System.outprinting子類的一般方法");
}
publicstaticvoidmain(String[]args){
//編譯時類型和運行時類型完全一樣,因此不存在多態(tài)
BaseClassbc=newBaseClassO;
〃輸出父類be對象的成員變量值:6
System,outprintlnfbc.book);
bc.test();
bc.base();
〃編譯時類型和運行時類型完全一樣,因此不存在多態(tài)
SubClasssbc=newSubClassO;
〃輸出子類對象sbe的成員變量值:abc
System,outprintln(sbc.book);
sbc.testO;
sbc.subO;
//下面調用將執(zhí)行從父類繼承到的base。方法
sbc.baseO;
//編譯時類型和運行時類型不一樣,發(fā)生多態(tài)發(fā)生
BaseClassployBc=newSubClass();
〃訪問的是父類對象的實例變量
System.outprintlnfployBc.book);
//執(zhí)行從父類繼承到的base。方法
ployBc.base();
//調用將執(zhí)行當前類的test。方法
ployBc.testO;
〃ployBc.subf);因為編譯時類型是BaseClass,沒有供應sub。方法,所以編譯會
出現(xiàn)錯誤
}
)
因為子類是一種特殊的父類,因此java允許把一個子類對象干脆賦給一個父類引用變量,無須
任何類型轉換,或者被稱為向上轉型,向上轉型由系統(tǒng)自動完全。
對象的實例變量不具備多態(tài)性。
注:
引用變量在編譯階段只能調用其編譯時類型所具有的方法,但運行時則執(zhí)行它運行時類型所具
有的方法。因此在編寫Java代碼時,引用變量只能調用聲明該變量時所用類里包含的方法。例
如:Objectp=newPerson。代碼定義了一個變量P,則這個P只能調用Object類的方法,而
不能調用Person類里的方法。
假如須要讓這個引用變量調用它運行時類型的方法,則必需把它強制類型轉化成運行時的類型,
強制類型轉換符須要借助于類型轉換運算符,用法是(type)variable
強制類型轉換須要留意:
基本類型之間的轉換只能在數(shù)值類型之間進行,這里所說的數(shù)值類型包括,整數(shù)型、字符型和
浮點型;但數(shù)值類型和布爾類型之間不能進行類型轉換。
引用類型之間的轉換只能在具有繼承關系的兩個類型之間進行,假如是兩個沒有任何繼承關系
的類型,則無法進行類型轉換。
考慮到強制類型轉換時可能出現(xiàn)異樣,因此進行類型轉換之前應先通過instanceof運算符來推
斷是否可以成功轉換。
留意:
當把子類對象賦給父類引用變量時,被稱為向上轉型,這種轉型總是可以成功的,這也從另一
個側面證明白子類是一種特殊的父類。這種轉型只是表明這個引用變量的編譯時類型是父類,
但實際執(zhí)行它的方法時,照舊表現(xiàn)出子類對象行為方式。但把一個父類對象賦給子類引用變量
時,就須要進行強制類型轉換,而且還可能在運行時產生ClassCastException異樣,運用
instanceof運算符可以讓強制類型轉換更平安。
Instanceof運算符:
Instanceof運算符前一個操作數(shù)通常是一個引用類型變量,后一個操作數(shù)通常是一個類(也可
以是接口),它用于推斷前面的對象是否是后面的類,或者其子類、實現(xiàn)的實例。假如是,則返
回ture,否則返回false.
在運用instanceof運算符時須要留意:instanceof運算符前面操作數(shù)的編譯時類型要么與后面
的類相同,要么與后面的類具有父子繼承關系,否則會引起編譯錯誤。
publicclassinstanceofTest{
publicstaticvoidmain(String[]args){
〃聲明hello時運用Object類,則hello的編譯類型是Object
“Object是全部類的父類,但hell。變量的實際類型是String
Objecthello="hello";
System.oi7tprintln((helloinstanceofObject));
〃String和Object類存在繼承關系,可以進行instanceof運算,返回true
System.oi7tprintln((helloinstanceofString));
//Math和Object類存在繼承關系,可以進行instanceof運算,返回false
System.oi7tprintln((helloinstanceofMath));
//String實現(xiàn)了Comparabel接口,所以返回true
System.oi7tprintln((helloinstanceofComparable));
Stringa="heno";
“String類和Math類沒有繼承關系,所以下面的代碼編譯無法通過
//System,out.println((ainstanceofMath));
}
)
4.8初始化塊:
初始化塊是一段固定執(zhí)行的代碼,它不能接受任何參數(shù)。因此初始化塊對同一個類的全部對象
所進行的的初始化處理完全相同。假如兩個構造器中有相容的初始化代碼,且這些初始化代碼
無須接收參數(shù),就可以把它們放在初始化塊中定義。
當創(chuàng)建java對象時,系統(tǒng)總是先調用該類里定義的初始化塊,相同類型的初始化塊之間按依次
執(zhí)行。初始化塊在執(zhí)行構造器之前執(zhí)行。
與構造器類型,創(chuàng)建一個java對象時,不僅會執(zhí)行該類的一般初始化塊和構造器,而且系統(tǒng)會
始終上溯到java.lang.Object類,先執(zhí)行java.lang.Object類的初始化塊,再起先執(zhí)行
java.lang.Object的構造器,依次向下執(zhí)行其子類的初始化塊,再起先執(zhí)行其子類的構造器…
最終才執(zhí)行該類的初始化塊和構造器,返回該類的對象。
靜態(tài)初始化塊:
假如定義初始化塊時運用了static修飾符,則這個初始化塊就變成了靜態(tài)初始化塊,也被稱為
類初始化塊(一般初始化塊負責對對象執(zhí)行初始化,類初始化塊則負責對類進行初始化)。靜態(tài)
初始化塊總是類相關的,系統(tǒng)將在類初始化階段執(zhí)行靜態(tài)初始化塊,而不是在創(chuàng)建對象時才執(zhí)
行。因此靜態(tài)初始化塊總是比一般初始化塊先執(zhí)行。
通常靜態(tài)初始化塊用于對類變量執(zhí)行初始化處理。
與一般初始化塊類型,系統(tǒng)在類初始化階段執(zhí)行靜態(tài)初始化塊時,不僅會執(zhí)行本類的靜態(tài)初始
化塊,而且還會始終上溯到java.lang.Object類,從最高父類起先始終到本類結束,依次執(zhí)行
每個類中的靜態(tài)初始化塊。
publicclassTest{
publicstaticvoidmain(String[]args){
newLeafQ;
newLeaf();
}
)
classRoot{
static{
System.outprintln("Root的靜態(tài)初始化塊");
)
{
System.outprintln("Root的初始化塊叱
)
publicRoot(){
System.outprintln("Root的無參構造器");
)
)
classMidextendsRoot{
static{
System.outprintln("Mid的靜態(tài)初始化塊");
)
(
System.out.println("Mid的初始化塊");
}
publicMid(){
System.outprintln("Mid的無參構造器");
}
publicMid(Stringmsg){
//通過this調用同一類中重載的構造器
this();
System.outprintlnC'Mid的帶有參數(shù)的構造器");
)
}
classLeafextendsMid{
static{
System.outprintln("Leaf的靜態(tài)初始化塊");
)
{
System.outprintln("Leaf的初始化塊");
)
publicLeaf(){
super("abc");
System,outprinting執(zhí)行Leaf的構造器");
)
}
Root的靜態(tài)初始化塊
Mid的靜態(tài)初始化塊
Leaf的靜態(tài)初始化塊
Root的初始化塊
Root的無參構造器
Mid的初始化塊
Mid的無參構造器
Mid的帶有參數(shù)的構造器
Leaf的初始化塊
執(zhí)行Leaf的構造器
Root的初始化塊
Root的無參構造器
Mid的初始化塊
Mid的無參構造器
Mid的帶有參數(shù)的構造器
Leaf的初始化塊
執(zhí)行Leaf的構造器
類初始化階段,先執(zhí)行最頂層父類的靜態(tài)初始化塊,然后依次向下,直到執(zhí)行當前類的初始化
塊。
對象初始化階段,先執(zhí)行最頂層父類的初始化塊、最頂層父類的構造器,然后依次向下,直到
執(zhí)行當前類的初始化塊、當前類的構造器
Java系統(tǒng)加載并初始化某個類時,總是保證該類的全部父類(包括干脆父類和間接父類)全部
加載并進行初始化。
靜態(tài)初始化塊和靜態(tài)成員變量的執(zhí)行依次與在源程序中排列依次相同。
第五章面對對象下
5.1java增加的包裝類
為了解決8種基本類型的變量不能當成Object類型變量運用的問題,java供應了包裝類的概
除了int和char有點例外,其他的基本數(shù)據類型對應的包裝類都是將其首字母大寫即可。
自動裝箱和自動拆箱用法:
publicclassAutoBoxingUnboxing{
publicstaticvoidmain(String[]args){
//干脆把一個基本類型變量賦給Integer對象
IntegerinObj=5;
//干脆把一個boolean類型變量賦給Object類型變量
ObjectboolObj=true;
//干脆把一個Integer對象賦給int類型變量
intit=inObj;
if(boolObjinstanceofBoolean){
//先把Object對象強制類型轉換為Boolean類型,再賦給boolean變量
booleanb=(Boolean)boolObj;
System.out.printin(b);
}
)
}
包裝類還可實現(xiàn)基本類型變量和字符串之間的轉換。把字符串類型的值轉換為基本類型的值有
兩種方式:
1)利用包裝類供應的parseXxx(Strings)靜態(tài)方法
2)利用包裝類供應的Xxx(Strings)構造器
String類供應了多個重載的vahieOf。方法,用于將基本類型變量轉換成字符串。
publicclassPrimitive2String{
publicstaticvoidmain(String[]args){
StringintStr="123";
//把一個特定的字符串轉換成int變量
intit1=Integer.parseZz?4intStr);
intit2=newInteger(intStr);
System.outprintln(it2);
StringfloatStr="4.56";
//把一個特定的字符串轉換成float變量
floatft1=Float.parse7*7oa4floatStr);
floatft2=newFloat(floatStr);
//把一個float變量轉換成String變量
StringftStr=String.va/〃eO/(2.345f);
System.outprintln(ftStr);
//把一個double變量轉換成String變量
StringdbStr=String.ra7tzeC>43,344);
System.out.println(dbStr);
//把一個boolean變量轉換成String變量
StringboolStr=String.ra/z7e(94true);
System.ou^.println(boolStr.toUpperCase());
假如希望把基本類型變量轉換成字符串,還有一種更簡潔的方法:將基本類型變量和””進行
連接運算,系統(tǒng)會自動把基本類型變量轉換成字符串。
雖然包裝類型的變量時引用數(shù)據類型,但包裝類的實例可以與數(shù)值類型的值進行比較,這種比
較是干脆取出包裝類實例所包裝的數(shù)值來進行比較的。
publicclassTestDemo{
publicstaticvoidmain(String[]args){
Integera=newInteger(6);
System.out.println(a>5);
//兩個包裝類實例進行比較時,只有兩個包裝類引用指向同一個對象時才返回ture
System.outprintln(newInteger(2)==newInteger(2));
}
}
系統(tǒng)把一個“28-127之間的證書自動裝箱成Integer實例,并放入了一個名為cache的數(shù)組
中緩存起來。假如以后把一個“28-127之間的整數(shù)自動裝箱成一個Integer實例時,事實上是
干脆指向對應的數(shù)組元素,因此“28-127之間的同一個整數(shù)自動裝箱成Integer實例時,恒久
都是引用cache數(shù)組的同一個數(shù)組元素,所以它們都相等。但假如整數(shù)不在這個范圍內,則會
重新創(chuàng)建一個Integer實例。
publicclassTestDmo2{
publicstaticvoidmain(String[]args){
Integera=2;
Integerb=2;
System,outprintln(a==b);//true
Integerbiga=128;
Integerbigb=128;
System.6?utprintln(biga==bigb);//false
5.2處理對象
對象打印的誤區(qū):
publicclassPrintobject{
publicstaticvoidmain(String[]args){
Personp=newPerson("Peter");
//假如想打印P對象的內容,下面兩種方法都不行以,打出來的都是地址值
//Object類供應的toString。方法總是返回該對象實現(xiàn)類的“類名+@+
hashCode"的值
System.oi2tprintln(p);
System.out.println(p.toStringO);
)
}
classPerson{
privateStringname;
publicPerson(Stringname){
=name;
重寫toString()方法,通過重寫,就可以讓系統(tǒng)在打印Apple對象時打印該對象的“自我描述”
內容
publicclassToStringTest{
publicstaticvoidmain(String[]args){
Applea=newApple("red",100);
//打印Apple對象
System.outprintln(a);
classApple{
privateStringcolor;
privatedoubleweight;
//供應有參數(shù)的構造器
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中測試兩個變量是否相等有兩種方式,一種是利用==運算符,一種是利用equals。方法。
當運用==來推斷兩個變量是否相等時,假如兩個變量是基本類型變量,且都是數(shù)值類型(不愿
定要求數(shù)據類型嚴格相同),則只要兩個變量的值相等,就將返回true.
對于兩個引用類型變量,只有他們指向同一個對象時,==推斷才會返回true。==不行用于比較
類型上沒有父子關系的兩個對象。
publicclassEqualTest{
publicstaticvoidmain(String[]args){
intit=65;
floatfl=65.0f;
System.outprintln("65和65.0是否相等?"+(it==fl));
//true
charch='A';
System.outprintln("65和A是否相等?"+(it==ch));
//true
Stringstrl=newString("hello");
Stringstr2=newString("hello");
System.outprintln("strl和str2是否相等?"+(strl==str2));
//false
System.outprintln("strl是否equalsstr2?"+(strl.equals(str2)));
//true
當Java程序干脆運用形如"hello”的字符串干脆量(包括可以在編譯時就計算出來的字符串
值)時,JVM將會運用常量池來管理這些字符串;當運用newString("hello")時,JVM
會先運用常量池來管理“hello”干脆量,再調用String類的構造器來創(chuàng)建一個新的String對
象,新創(chuàng)建的String對象被保存在堆內存中。換句話說,newString(“hello”)一共產生了
兩個字符串對象。
publicclassStringCompareTest{
publicstaticvoidmain(String[]args){
//si干脆引用常量池中的“瘋狂java”
Stringsl="瘋狂java";
Strings2="瘋狂";
Strings3="java";
//s4s5后面的字符串值可以在編譯時就確定下來,它們都干脆引用常量池中的
“瘋狂java”
Strings4="瘋狂"+"java";
Strings5="瘋狂"+"java";
//s6后面的字符串值不能在編譯時就確定下來
Strings6=s2+s3;
〃s7引用堆內存中新創(chuàng)建的String對象
Strings7=newString("瘋狂java");
System.out.println(sl==s4);//true
System,outprintln(s1==s5);//true
System,outprintingsl==s6);//false
System,outprintln(s1==s7);//false
JVM常量池保證相同的字符串干脆量只有一個,不會產生多個副本。
String已經重寫了Object的equals。方法,String的equals。方法推斷兩個字符串相等的標
準是:只要兩個字符串所包含的字符序列相同,通過equals。比較將返回true,否則返回false
類成員不能訪問實例成員
假如一個類始終只能創(chuàng)建一個實例,則這個類被稱為單例類
publicclassSingletonTest{
publicstaticvoidmain(String[]args){
//創(chuàng)建Singleton對象不能通過構造器,只能通過getlnstance方法得到實例
Singletons1=Singleton.ge血stazzceO;
Singletons2=Singleton.getlnstance^;
System,outprintingsl==s2);
}
)
classSingleton{
//運用一個類變量來緩存曾經創(chuàng)建的實例
privatestaticSingletoninstance,
//對構造器運用private修飾,隱藏該構造器
privateSingleton(){}
//供應一個靜態(tài)方法,用于返回Singleton實例
//該方法可以加入自定義限制,保證只產生一個Singleton對象
publicstaticSingletongetlnstance(){
//假如Instance為Null,,則表明還不曾創(chuàng)建singleton對象
//假如intstance不為null,則表明已經創(chuàng)建了Singleton對象,將不會重新創(chuàng)建
新的實例
if(zz2stence==null){
instance=n.^NSingleton();
}
returninstance,
5.4final修飾符
Final修飾的變量不行被變更,一旦獲得了初始值,該final變量的值就不能被重新賦值。因此
java語法規(guī)定:final修飾的成員變量必需由程序員顯式的指定初始值。
Final修飾的類變量、實例變量能指定初始值的地方如下:
類變量:必需在靜態(tài)初始化塊中指定初始值或聲明該類型變量時指定初始值,而且只能在兩個
地方的其中
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025上半年安徽合肥市廬江縣事業(yè)單位招聘工作人員66人高頻重點提升(共500題)附帶答案詳解
- 2025上半年四川省隆昌縣事業(yè)單位招聘75人歷年高頻重點提升(共500題)附帶答案詳解
- 2025上半年四川省合江縣事業(yè)單位招聘8人歷年高頻重點提升(共500題)附帶答案詳解
- 2025上半年四川南充南部縣事業(yè)單位招聘工作人員191人歷年高頻重點提升(共500題)附帶答案詳解
- 2025上半年事業(yè)單位聯(lián)考湖北省宜昌市招聘(494人)高頻重點提升(共500題)附帶答案詳解
- 新版2020年監(jiān)理員模擬考試題庫388題(含答案)
- 2025年度3D打印服務內部承包協(xié)議2篇
- 2025年度海洋工程裝備制造工程轉讓協(xié)議2篇
- 2025年度二零二五年度城市供熱安全監(jiān)測合同
- 2024年度文化創(chuàng)意產業(yè)分租合作合同3篇
- 河南省焦作市2023-2024學年高二上學期1月期末考試數(shù)學試題(含答案解析)
- 客戶經理貸款營銷思路
- 病理組織切片技術課件
- 生產線能耗分析報告模板
- 上海市松江區(qū)2023-2024學年高一上學期期末質量監(jiān)控數(shù)學試卷 (解析版)
- 校外安全教育課件
- 微生物實驗室生物安全培訓
- 農村房屋建設技術方案
- 四川省成都市2023-2024學年八年級上學期期末數(shù)學試題(無答案)
- 人教版三年級數(shù)學上冊第五單元:倍數(shù)問題提高部分(解析版)
- 臍疝護理查房
評論
0/150
提交評論