在這里記錄一下自己回顧Java基礎(chǔ)時,一些覺得掌握的還不牢固的基礎(chǔ)知識,查漏補缺!
Java程序初始化順序
三個原則
- 靜態(tài)對象優(yōu)先于非靜態(tài)對象,靜態(tài)對象只會初始化一次
- 父類優(yōu)先于子類
- 成員變量則是根據(jù)定義的順序進行初始化
各種代碼塊的初始化順序則如下:
- 父類靜態(tài)變量,靜態(tài)代碼塊
- 子類靜態(tài)變量,子類靜態(tài)代碼塊
- 父類費靜態(tài)變量,代碼塊
- 父類構(gòu)造方法
- 子類非靜態(tài)變量,代碼塊
- 子類構(gòu)造方法
Java對象的作用域
成員變量:作用范圍與類的實例對象的作用范圍相同
靜態(tài)變量:只要一個類被加載,jvm就會給該類的靜態(tài)變量分配存儲空間
局部變量:僅限于該類所在的花括號內(nèi)
構(gòu)造方法
當(dāng)父類沒有提供無參的構(gòu)造方法時,子類的構(gòu)造方法中必須顯式的調(diào)用父類的構(gòu)造方法;
當(dāng)提供了無參構(gòu)造方法,則無需顯式調(diào)用,因為編譯器會默認(rèn)調(diào)用父類無參構(gòu)造方法;
在實例化對象時,先執(zhí)行父類的構(gòu)造方法,然后才是子類
clone方法的理解
- 首先,為什么會有該方法?
這里涉及到Java方法的兩種傳遞參數(shù)方式:
處理基本數(shù)據(jù)類型時,采用的是按值傳遞;
此外,當(dāng)處理其他數(shù)據(jù)類型時,都是采用的按引用傳遞,包括在使用“=”賦值時也是如此
這樣就會導(dǎo)致一個問題:當(dāng)需要創(chuàng)建一個和當(dāng)前已有對象相同的對象,又需要對其中一個的修改不會影響到另一個對象時,使用一般的賦值操作顯然無法達到該目的,因此提供了clone方法來提供這個能力
- 如何實現(xiàn)clone方法?
在將這個之前,先看兩個概念:
淺復(fù)制:被復(fù)制的對象的所有變量都和原來的對象有相同的值,而所有對其他對象的引用仍然指向其原來的對象;
深復(fù)制:會將原對象所有引用的對象全都復(fù)制一遍
下面看如何實現(xiàn)clone方法:
- 使目標(biāo)類實現(xiàn)Cloneable接口,該接口中沒有任何方法,只是一個標(biāo)識接口
- 重寫clone()方法
- 在該方法中返回super.clone(),也就是會調(diào)用至Object的clone方法
上面是淺復(fù)制的實現(xiàn)方法,若需實現(xiàn)深復(fù)制,則需要對對象中的非基本類型數(shù)據(jù)都調(diào)用clone方法;
注意,這里需要這些屬性所屬類全都實現(xiàn)clone方法才行
組合和繼承
繼承:is-a的關(guān)系
組合: has-a關(guān)系
能使用就盡量不要使用繼承
多態(tài)
Java中的多態(tài)主要表現(xiàn)為兩種方式:
- 方法的重載overload:編譯時多態(tài),在編譯期間就可以確定調(diào)用哪一個方法
- 覆蓋override:運行時多態(tài),只有在運行時,才可以確定內(nèi)存中實例化的是哪一個對象
這里需要注意:只有方法才有多態(tài)的概念,類中的成員變量并沒有方法的概念,因為成員變量是在編譯期間就確定了的;
因此,成員變量的取值為new對象定義的類型的值
舉例如下:
BaseClass b = new SubClass()
假設(shè)sub是base的子類,這時打印b.age,此時打印出的是base中定義的值而非sub定義
接口與抽象類
接口,強調(diào)功能的特定實現(xiàn),是has-a的關(guān)系
抽象類,強調(diào)所屬關(guān)系,是is-a的關(guān)系
static代碼塊常用來初始化靜態(tài)變量
switch支持string類型,其實也是先判斷字符串的hashcode是否相同,若相同, 再調(diào)用equals方法進行匹配
volatile
可以提供可見性,部分有序性,但是無法保證原子性,因此其還是無法替代synchronized關(guān)鍵字
按值傳遞與引用傳遞
- 值傳遞:原始數(shù)據(jù)類型,會擁有不同的存儲空間,對參數(shù)的修改不會影響到原值
- 引用傳遞:傳遞的是對象的地址,二者指向同一內(nèi)存地址,對形參的修改會影響到實參
Java的異常處理用到了多態(tài)的概念,在進行異常捕獲時,如果需要捕獲多個,應(yīng)該先捕獲子類,再捕獲基類;
否則若順序相反,子類異常就不會被捕獲到了