java基礎小總結(2)

Day07:

1.如果局部變量和全局變量都有相同的數據類型和變量名,先調用局部變量,實現就近原則;

2.匿名對象由於侷限性的原因,一般只調用一次,且只是當作爲實際參數傳遞的時候使用;

3.面嚮對象語言的三大基本特徵:封裝,繼承,多態

4.封裝的好處:安全,方便,用private(只能在本類中訪問)體現;

5.構造函數是爲了顯示初始化;是沒有返回值類型的

6.在構造函數可以調用一般函數,但是在一般函數中不可以調用構造函數;

7.構造函數定義的細節:

1、構造函數是用來創建對象的,它不需要書寫返回值類型。

2、構造函數的名字要求必須和當前的類名一致。因此構造函數的名稱書寫和類名一致。

3、參數列表,可以和一般函數的參數列表一樣。

8.構造函數的作用:就是爲了給對象初始化時使用的。(就是爲了給非靜態成員變量初始化值使用)。

9.在new的類中,只要寫了構造函數,編譯器就不會自動添加無參構造。所以參數列表必須得一樣,不然報錯。如果沒有寫構造方法,那麼編譯器在編譯的時候會自動添加一個無參構造方法(這個方法稱爲默認無參構造函數);

10.構造方法可以以重載的方式存在同一個類中;

11.構造函數和一般函數異同

1、它們的執行時間不同:

構造函數是在創建對象的過程中執行。當對象創建完成了,構造函數就已經執行結束。

一般函數執行時間有兩種情況:

1)      如果調用其他類中的函數時:一般函數通過是在對象創建完成之後,通過對象的引用來調用。

2)      如果調用本類中的函數時:什麼時候使用,什麼時候調用。

 

2、它們的調用次數不同:

構造函數只有在new對象的時候,會被調用,一旦對象創建完成,我們不能手動的人爲去調用構造函數。

一般函數可以通過對象隨意的調用,沒有次數限制。

 

3、它們互相調用問題:

在構造函數中可以去調用一般的函數,但是在一般的函數中不能調用構造函數。

(構造函數和一般函數的區別:

1. 構造函數沒有返回值類型,而一般函數的有返回值類型;

2. 構造函數只有在新建對象的時候纔會使用,因爲新建而存在,隨着新建的結束而消失,不能隨意的調用;而一般函數可以在同一個類或者不同類中存在,調用次數不限,如果在同一個類中定義則可以通過函數名直接調用;如果在不同類中定義,則調用的時候需要通過對象名調用;隨着調用而存在,隨着方法的結束而消失;

3. 互相調用問題:構造函數可以調用一般函數,而一般函數不可以調用構造函數;)

 

12.怎麼使用this來調用其它的構造函數?

  this調用其它構造函數的格式:  this(參數列表);  //相當於 構造函數(參數列表)

在Java中只要是通過名稱調用函數,那麼調用的都是一般函數,構造函數之間不能通過函數名調用。

12.在使用this調用構造函數的時候注意的問題:

1、構造函數之間不能相互嵌套調用,這樣就會導致無限制的調用構造函數,導致永遠無法停止調用。

2、this調用構造函數,必須放在構造函數中的第一句。我們通過this調用構造函數的目的是希望通過其他的構造函數完成初始化動作,因此要求其他構造函數的初始化必須在本構造函數中語句執行之前先初始化完成。

13.this的第二個功能:在構造方法或者通過對象名調用類中方法的時候,語句中是有隱藏this變量,此時的this保存的就是誰調用,就是誰在堆內存中new的地址名,所以可以訪問到new完之後堆內存裏的成員變量的值;

14.this的第三個功能是區分成員變量和局部變量,誰調用,this就代表誰;

 

想使用this,必須有對象,因爲this記住的是對象在堆內存產生的地址名

 

Day08:

1.每個類都有默認的無參構造函數;

2.對new出來的對象類執行流程,先執行靜態代碼塊(以後會經常使用,主要是爲了初始化靜態成員變量,另外靜態代碼塊只會執行一次),如果多個就從上往下執行;對於調用構造函數的時候有隱式三步(1. Super(),2.對成員變量顯示初始化,3.執行構造代碼塊),如果有多個構造代碼塊,則也是按照上下順序依次執行;

3.靜態函數中不能有非靜態成員變量和非靜態成員函數;而非靜態成員函數中可以有靜態成員變量和靜態函數;

4.Static修飾的成員變量和成員函數在其他類中可以通過類名和對象名調用,與對象無關,主要和類有關,隨着類的加載而執行和加載;而非靜態函數和非靜態成員變量在其他類中只可以通過對象調用;

5.靜態成員變量和非靜態成員變量的區別:

a.創建的時間不同,靜態的會隨着類的加載而加載,而非靜態的會隨着對象的創建而加載;

b.在內存的位置不同,靜態的會是在類加載的方法區中的靜態區加載,而非靜態的會是在對象的創建在堆內存中加載;

c.在內存中的消失時間不同,靜態的只有當JVM退出的時候纔會消失,而非靜態的會隨着對象的消失而消失;

d.初始化的時間不同,靜態變量會隨着類的加載而加載,會當時就賦值初始化了,而非靜態的則隨着對象的創建才被初始化賦值;

6.在類加載的時候,JVM會先加載類中的所有靜態成員變量,當把所有的靜態成員變量加載完成之後,開始給類中的所有靜態成員變量進行默認初始化,當類中的所有靜態成員變量默認初始化完之後,會接着開始給所有靜態成員變量進行顯示的賦值操作。只有類中所有的靜態成員變量顯示賦值結束之後,靜態代碼塊纔會運行。

小結:

1、靜態代碼塊隨着類的加載而執行,僅執行一次

2、靜態代碼塊的作用:給類進行初始化。

7.構造函數的隱式的三步:a. super() ; b. 成員變量顯示初始化 ; c .構造代碼塊執行

8.類的加載過程:

a.首先在方法區中加載類的class文件到非靜態區,然後將靜態的成員變量,靜態成員方法和靜態代碼塊加載到靜態區;

b.所有的靜態加載完成後再將靜態成員變量進行一步步的默認初始化,然後再進行顯示初始化;

c.靜態成員變量顯示初始化完成後再運行靜態代碼塊;

d.所有的靜態代碼塊加載完成後才代表整個類的加載完成;

 

創建對象的加載過程:

a.使用關鍵字new創建對象,會在堆內存中開闢空間並隨機分配地址名;

b.在開闢的空間中會將所有的非靜態成員變量加載到堆內存分配空間,進行默認初始化;

c.加載完成後會調用匹配的構造函數:(隱式三步)1.super();2.將所有的非靜態成員變量進行顯示初始化;3.運行構造代碼塊;最後運行構造函數的其他代碼;

d.構造函數執行完成,對象創建完畢;

9.單例設計模式:

A.爲了實現只能創建一個對象,所以要把所有的構造函數都得私有化,不能讓其他類調用;

B.構造函數私有化了,那麼只能自己在內部進行對象的創建;

C.同時需要一個對外的函數實現返回已創建的對象,但是由於其他類不能創建新對象,所以調用函數不能通過對象名調用,只能是類名調用,所以這個函數必須得是靜態的,那麼return的對象也得是靜態的;

D.這樣就能通過類名來調用函數返回給調用者創建的對象;

E.但是上述的創建過程還有一個漏洞,就是創建新對象的表達式沒有被私有化,雖然靜態修飾了,但是還是能通過類名進行調用,這樣不符合要求,所以創建新對象的表達式也得被私有化,這樣外部就訪問不到,創建不了其他新對象了。

F.完美的實現了單例設計模式

 

Day09:

1.static修飾的函數裏面不能有this,super,因爲this記住的是對象的地址名,和對象有關,super是調用了父類的構造函數,構造函數也是和對象有關,所以不可以;

2.this和super的區別:

1) this表示的本類中的成員,super表示父類中的成員。

2) 在Java中,this是一個引用變量,它中保存的是當前調用這個函數的那個對象的內存地址。

super僅僅表示的父類的內存空間。但不是父類的對象。super僅僅只是一個標記,標記哪個是父類。

3) this表示子類對象在堆中開闢的整個空間,而super標記的是子類對象開闢空間中的父類所佔的空間。

注意:在開發中,通常父類中已經定義了成員變量,子類在繼承後直接使用就可以了,不需要再次定義新的成員變量。

3.方法(函數)的特點:

函數重載(overload): 發生在同一個類中

      方法名相同、參數列表不相同。和返回值沒有關係

函數重寫(override): 發生在子父類中

         方法名相同、參數列表相同、返回值類型相同 (子父類中的方法一模一樣)

4.子類在複寫父類的函數時,子類的方法訪問權限,必須大於等於父類的權限。父類中被private修飾的成員變量和成員函數不能被調用和重寫;

5.被final修飾的變量編譯後爲常量,且變量名必須大寫,以示區分;

6.抽象函數的方法,子類就一定得複寫所有的抽象函數,且抽象函數一定得用abstract修飾.

7.一旦某個類中有了抽象的函數這個類就變成抽象類了。同樣的類名也需要abstract修飾,重點是該抽象函數不能有方法體;

8.接口的默認修飾符是public abstract,所以重寫接口的實現函數的修飾符一定得是public

9.final小結:

    1) 被final修飾的成員變量,編譯後變爲常量,不能修改其值;

    2) 被final修飾的成員函數,不能被子類方法重寫;

3) 被final修飾的類,不能被子類繼承;

4) final它可以修飾類,可以修飾成員(成員變量、成員函數),修飾局部變量。不能修飾構造函數;

10.抽象類被繼承抽象函數必須得複寫,有抽象函數的類就是必須的抽象類;但是抽象類裏不一定就一定有抽象函數;

11.子類想調用父類函數,必須在複寫的子類函數體中寫super.函數名();

12.抽象類一定有子類,但要是沒有子類編譯也不會報錯,也有父類,至少是Object類;抽象類無法被創建對象,不能實例化;必須有子類實現,抽象函數必須被複寫;如果抽象類能夠創建對象,那麼這個對象就可以調用抽象函數,但是抽象函數沒有方法體,沒有任何意義;

13.接口中的成員變量默認修飾符爲:public static final ,且變量名字母大寫;想調用就用接口名.變量名;

 

Day10:

1.接口中只能有成員變量和成員函數

2.在實現接口的類中調用接口中的成員變量就可以直接寫變量名,屬於有點繼承的關係;但是測試類想用就得是接口名.變量名調用;

3.如果接口裏的函數有不重寫會報錯嗎?會,實現了某個接口必須複寫接口中的所有函數

4.如果一個類實現了多個接口,且多個接口中有同個函數,那這個類複寫同樣的函數時就只需要複寫一次就可以,因爲函數都是沒有函數體,所有就不會有不確定性;

5.如果一個類實現了多個接口,且多個接口中有同個成員變量,那調用的時候得是接口名.變量名,不然編譯出錯,因爲有不確定性;

6.敲代碼:適配器代碼,設計模式的思想爲定義一個抽象類,複寫接口內的所有方法,但是函數體是空的,這樣調用和複寫起來就比較方便。但是適配器得是抽象的,因爲不是抽象的沒啥意義;

7.適配器爲什麼是抽象類?因爲不是抽象函數就能創建子類對象,但適配器裏的函數都是空函數體的,就算創建了對象,調用函數沒有任何意義;其實abstract可以不寫,但是菜鳥;

8.抽象函數的返回值只能的void嗎?  不是,也可以是其他類型,看具體的需求。

9.多態能發生在接口中嗎?/////////接口被實例化對象實現,是可以使用(接口名  對象名= new 實現類名()),這樣對象名可以調用實現類中的函數,類似於多態;

 

/*

這個就用了接口傳參,用實現類對象做實參,也是發生了多態,調用了實現類對象的函數;所以多態也是可以發生在接口中

*/

9.抽象類也可以實現多態,編譯和運行的規則和一般類一樣;

10.使用多態場景有:如果父類中的成員函數較多,且子類都想調用,那可以將子類名調用函數的方法體都提出取來,傳參爲父類類型。其他子類的特有函數可以使用instanceof關鍵字判斷,然後使用強制轉型進行向下轉型;

11.多態弊端總結:

在使用多態技術的時候,程序在編譯的時候,使用多態調用成員(變量和函數),要求被調用的成員在父類中一定要存在,如果父類中沒有編譯就會失敗。(不能使用子類特有功能或者屬性)

 

注意:只要有多態的地方,一定發生類型的提升(肯定是把子類對象使用父類類型在表示)。

1)什麼時候使用向下轉型:

         只要在程序中我們需要使用子類的特有屬性或行爲(方法、函數)的時候,纔會使用向下轉型。

2)無論是向上還是向下轉型,最終都是子類對象做着類型的變化。和父類對象沒有關係。

 

12.總結:

只要有多態,就會有類型的轉換。

把子類對象賦值給父類的引用,這時發生了向上的轉型(隱式類型轉換)。

如果我們需要使用子類的特有行爲或屬性,這時必須向下轉型,需要把父類的引用轉成具體所指的那個對象的類型。

在向下轉型的時候一定要做類型的判斷,防止ClassCastException異常的發生。

 

判斷格式:

if父類引用變量名  instanceOf  子類對象所屬的類名

{

進行轉換。

}

13.總結多態中成員使用規律:成員變量和靜態成員函數,編譯運行都看左邊(父類中的)。只有非靜態成員函數,編譯看父類,運行看子類對象。

14.個人總結抽象類和接口的區別:

a.接口裏只能寫成員變量和函數,且函數是抽象函數,默認修飾符爲public abstract,變量的默認修飾符是public static final即變量變成了常量,必須得有初始化值;抽象類裏可以寫成員變量和成員函數(包括靜態和非靜態),有構造函數(爲了給子類變量初始化但不能創建對象),可以有靜態代碼塊,成員函數可以是抽象或者是非抽象的,不一定必須得有抽象函數;

b.接口必須得實現,且實現類裏必須重寫接口裏的函數(注意函數修飾符的權限大小問題);抽象函數不一定得繼承,可以不被繼承,但是一旦被繼承了,那麼繼承類必須重寫抽象函數;(注:一旦有抽象函數,那麼這個類一定是抽象類)

c.接口是表示某些事物的額外功能;抽象類裏的抽象函數則是表示類中的行爲不能全部描述,所以寫成抽象函數;

d.接口的實現用關鍵字implements;抽象類被繼承的關鍵字爲extends;

e.接口是可以多實現,接口之間可以多繼承;而抽象類和類只能單繼承;

f.抽象類關鍵字不和private、static、final修飾符共存

  

Day11:

1.成員內部類:

Public修飾:

a.創建對象可以在外部類中創建,Inner in = new Inner();(隱藏意思:Outer.Inner in = new Outer.Inner();)然後放在外部類的函數裏,這樣在其他類中創建外部類的對象,在調用函數,就能調用內部類的函數

b.創建內部類對象可以在其他類中,這樣可以通過外部類對象調用創建內部類:Outer o = new Outer();    Outer.Inner in = o.new Inner();換成一行代碼爲:Outer.Inner in = new Outer().new Inner();

如果我們想要在其他類中調用內部類中的一般函數(非靜態函數),必須要使用內部類的對象來調用,所以我們要創建內部類的對象,創建方式:

new 內部類類名();--------->new Outer.Inner();

 

Static修飾:

如果在其他的類中想要調用靜態內部類中的靜態方法,我們可以先找到靜態內部類的類名,然後根據類名

其他類中來調用靜態內部類中的靜態函數和變量,操作如下所示:Outer.Inner.method();

外部類中調用靜態內部類中的靜態函數和變量,Inner.method();

注意:此時的內部類函數和變量要用static修飾

Private修飾:

當一個類中的成員被私有了,只能在這個類中訪問。

注意:被私有的成員內部類,只能在本類的其他方法中創建對象,然後外界去調用外部類的這個成員方法,通過這個成員方法在間接的讓內部類中的方法運行。

2.局部內部類:

注意:局部內部類不能被成員修飾符修飾。

注意:局部內部類只能在局部內部類所在的函數中訪問,出了函數無法訪問。

內部類定義在局部時,只能訪問被final修飾的局部變量。如果不被final修飾會報錯誤。

 

 3.匿名內部類:

格式:

new  父類 或 接口(){

複寫父類或實現接口中的函數

};

說明:

1)注意大括號後面有一個英文的分號,不能省略。

2)匿名內部類格式是固定的,以後在開發中遇到以上格式,要知道是匿名內部類格式即可。

3)匿名內部類只能創建在外部類的局部位置,且如果想通過匿名內部類調用其中的多個函數,可以將匿名內部類賦值給父類或者接口對象。再用對象名調用函數。

即:父類/接口  變量名= new 父類/接口(){

複寫或者實現父類、接口中的函數

};

變量名.函數名1;

變量名.函數名2;

 

4.總結:

1、什麼情況下使用匿名內部類?

如果我們定義一個類,實現了接口 或繼承父類,僅僅只爲複寫父類或者實現接口中的方法, 這時我們專門定義的這個類有點多餘,這時可以使用Java中提供的匿名內部類完成。

2、匿名內部類都是接口或者父類的實現類或子類對象。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章