封裝:將資料和行為組合成一個物件,并向物件的使用者隱藏實作細節
-
類的細節
-
一個物件變數并沒有實際包含一個物件,Java中任何物件變數的值都是對存盤在另外一個地方的一個物件的參考,new運算子的回傳值也是一個參考
-
如果需要回傳一個可變資料域的拷貝,就應該使用clone()
-
區域變數不會自動初始化為null,必須通過new或將他們設定為null來初始化
-
-
構造器
-
如果構造器中沒有顯式給域賦初值,那么就會被自動賦予初值:數值為0,布林值為false,物件參考為null
-
構造器的具體處理步驟
-
所有資料初始化為默認值(0,false或null)
-
按照類宣告中出現的次序,執行所有域初始化陳述句和初始化塊
-
如果構造器第一行呼叫了第二個構造器,則執行第二個構造器主體(其他構造器呼叫必須在第一行,如果想同時呼叫父類構造器和本類其他構造器會報錯,可以另外定義函式解決)
-
執行本構造器主體
-
-
-
方法與靜態方法
-
方法
-
除了有括號內的顯式引數,還有出現在方法名前的類物件,被稱為隱式引數this,它是呼叫該方法的物件本身的參考,有些人把隱式引數稱為方法呼叫的目標或者接收者
-
方法引數
-
按值呼叫:方法接收的是呼叫者提供的值
-
按參考呼叫:方法接收的是呼叫者提供的變數地址
-
Java總是采用按值呼叫,方法不能修改傳遞給它的任何引數變數的值
-
然而方法引數有兩種型別:基本資料型別和物件參考
-
對于基本資料型別,方法無法修改引數的值
-
而物件參考可以被方法修改物件中的實體域(這里的引數是物件地址,而修改的是物件的值)
-
驗證Java按值參考的例子:無法通過swap(Object o1, Object o2)來交換這兩個物件
-
-
-
方法簽名:方法名和方法引數型別構成方法簽名,回傳型別不是方法簽名的一部分
-
-
靜態方法
-
是一種不能操作物件的方法,它屬于類而不屬于類的物件,可以看作是一種沒有隱式引數this的方法,靜態方法可以訪問自身類中的靜態域
-
不推薦使用物件來呼叫靜態方法,使用物件呼叫時沒有多型,參考是什么型別就會去調對應型別的靜態方法
-
-
-
static實體域
-
屬于類而不屬于類物件
-
每個類中只有一個這樣的域,所有的類物件共享
-
-
final實體域和方法
-
定義為final的實體域在構建物件時必須初始化,并且在之后的操作中,不能再對它進行修改
-
這里的修改指的是不能將變數中的物件參考指向其他物件,但是被參考物件的狀態是可以改變的
-
宣告為final的方法子類不能覆寫
-
總結
-
修飾類:不能被繼承
-
修飾方法:不能被覆寫
-
修飾變數:不能被改變
-
-
-
繼承:復用已存在類的域和方法
-
super關鍵字
-
使用super來呼叫父類方法
-
super與隱式引數this不同,因為super并不是一個物件的參考,它只是一個指示編譯器呼叫父類方法的特殊關鍵字
-
使用super呼叫構造器的陳述句必須是子類構造器的第一條陳述句
-
-
抽象類
-
包含一個或多個抽象方法的類必須宣告為抽象的
-
除了抽象方法,抽象類還可以包含具體資料和具體方法
-
抽象類不能被實體化,但是可以定義一個抽象類的物件變數,它只能參考一個非抽象的子類物件
-
-
getClass()
-
回傳一個物件所屬的類
-
回傳的是變數實際指向的物件的類,比如父類變數參考子類物件,那么回傳的其實是子類(和多型一樣實際操作的物件是隱含引數this)
-
-
equals()
-
撰寫一個完美的equals()方法
-
檢測隱式引數this和顯式引數otherObject是否參考同一個物件
-
檢測otherObject是否為null
-
比較隱式引數this和顯式引數otherObject是否是同一個類
-
若equals語意在每個子類中有所改變,就用getClass()是否是相同的(子)類
-
否則用instanceof 是否是同一個父類
-
-
開始比較域,基本型別用==,物件域使用equals()
-
-
如果在子類中重新定義equals,就要在其中包含呼叫super.equals()
-
如果重新定義equals,那么必須重新定義hashCode方法
-
因為equals與hashcode的定義必須一致,如果x.equals(y)回傳true,那么x.hashCode()就必須與y.hashCode()具有相同的值
-
null安全的方法Objects.hashCode(obj),引數為null會回傳0
-
組合多個散列值的方法,呼叫Objects.hash(param1, param2...),這個方法會對各個引數呼叫Objects.hashCode(),并組合這些散列值
-
陣列型別的域,可以使用Arrays.hashCode()方法
-
標準庫中你會看到很多成對出現的介面和使用工具類,如Object/Objects, Collection/Collections, Path/Paths等
-
-
int的==陷阱
-
整形變數使用 == 運算子比較時會進行自動裝箱,使用Integer.valueof()來創建Integer實體,然后就是兩個Integer物件的比較了
-
而整數型別在-128~127之間時,會使用快取(在IntegerCache類中有一個Integer陣列,用以快取當數值范圍為-128~127時的Integer物件)
-
如果已經創建了一個相同的整數,那么創建一個新的相同整數時不會使用new關鍵字,而是用已經快取的物件,兩個物件指向同一地址
-
所以此時 == 會相等
-
-
-
覆寫父類的方法
-
子類覆寫父類方法,可見性不能比父類方法可見性低
-
原因是這樣與多型沖突:假設現在有一個父類變數指向一個子類物件,呼叫子類中重寫的方法,如果此時子類中可見性更低,那么方法就無法被訪問,這樣多型就失效了
-
多型:一個物件變數可以指示多種實際型別的現象
-
動態系結:運行時能自動地選擇呼叫哪個方法的現象,
- 比如父類和子類都有getSalary()方法,現宣告一個父類物件Employee e,而將它指向一個子類物件參考Manager m,那么呼叫e.getSalary()時實際呼叫的是Manager的方法(因為是通過this自參考來呼叫物件的方法)
-
若父類變數指向子類物件參考,呼叫子類定義而父類未定義的方法是非法的,因為此方法不是父類的方法
- 理解方法呼叫
-
編譯器查看物件的宣告型別和方法名,這一步將得到該類和父類中public的所有名為f的方法(所有可能被呼叫的方法)
-
將呼叫時提供的方法引數與上一步找到的所有方法引數匹配,這被稱為多載決議,若找到多個匹配則會報錯,
- 多載呼叫哪個方法,和引數的參考型別相關,和實際指向的型別無關
-
根據隱式引數的實際型別確定呼叫方法指令
-
動態系結確認最適合的被調方法
-
- 理解方法呼叫
-
總結:能夠呼叫哪些方法取決于參考,實際呼叫的方法取決于參考指向的物件,無論呼叫哪個方法,都是在一個實際的物件上執行的,即隱含引數this執行
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/144247.html
標籤:Java
