day13
review
- 多型性?
父類的參考指向子類的物件
- 虛擬方法呼叫?
當我們通過變數名去呼叫子父類中同名、同參方法時,編譯時任務呼叫的是父類中的方法,實際執行時呼叫的是子類中重寫的方法
- 方法重寫(override)的具體規則
- 子類中重寫的
方法名、形參串列與父類中的相同 - 子類中重寫方法的
權限修飾符不小于父類中的方法 - 子類中重寫方法拋出的
例外不大于父類方法中拋出的例外 - 子類中重寫方法的
回傳值不大于父類方法的回傳值,具體表現為:- 當父類方法回傳值為
void或基本資料型別時,子類重寫方法的回傳值必須父類中的相同 - 當父類方法的回傳值為
參考資料型別A時,子類重謝方法的回傳值為相同的參考資料型別A或者A的子類
- 當父類方法回傳值為
開發中重寫時,經常直接復制父類方法宣告或者用快捷鍵補全
- super
呼叫父類中指定的構造器
- 為什么
super()和this()呼叫陳述句只能作為構造器中的第一條陳述句出現?
無論通過哪個構造器創建子類物件,需要保證先初始化父類,
目的:當子類繼承父類后,“繼承"父類中所有的屬性和方法,因此子類有必要知道父類如何為物件進行初始化
instanceof
- 向下轉型
引入:有了物件的多型性以后,記憶體中實際上是加載了子類特有的屬性和方法的,但是由于變數宣告為父型別別導致編譯時,只能呼叫父類中宣告的屬性和方法,子類特有的屬性和方法不能呼叫,

- 如何呼叫子類中特有的屬性和方法?
使用強制型別轉換符()
強制轉換時,可能出現
ClassCastException例外,為了避免上述例外,所以引入instacnceof
- 使用:
a instanceof A
判斷物件a是否為類A的實體,如果是,回傳true,否則回傳false
-
使用情景:為了避免在向下轉型時,出現
ClassCastException例外,因此在向下轉型之前先用instacnceof進行判斷,一旦回傳true,則進行向下轉型,否則不進行 -
如果
a instanceof A == true,則a instanceof B == true, 其中A是B的子類 -
練習
class Base {
int count = 10;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base {
int count = 20;
public void display() {
System.out.println(this.count);
}
}
public class FeildMethodTest {
public static void main(String[] args) {
Sub s = new Sub();
System.out.println(s.count); // 20
s.display(); // 20
Base b = s;
System.out.println(b == s); // true
System.out.println(b.count); // 10
b.display(); // 20
}
}
由上述練習:
- 若子類重寫了父類方法,就意味著子類里定義的方法徹底覆寫了父類里的同名方法,系統將不可能把父類里的方法轉移到子類中,
- 對于實體變數則不存在這樣的現象,即使子類里定義了與父類完全相同的實體變數,這個實體變數依然不可能覆寫父類中定義的實體變數
上述兩點體現為:方法的編譯看左邊,運行看右邊;變數的編譯運行都看左邊
實戰
public class InterviewTest {
public static void main(String[] args) {
Base base = new Sub();
base.add(1, 2, 3); // (1)
Sub s = (Sub)base;
s.add(1, 2, 3); // (2)
}
}
class Base {
public void add(int a, int... arr) {
System.out.println("base");
}
}
class Sub extends Base {
public void add(int a, int[] arr) {
System.out.println("sub_1");
}
public void add(int a, int b, int c) {
System.out.println("sub_2");
}
}
// (1)sub_1
// (2)sub_2
Object類
Object是所有類的根父類- 如果在類的宣告中未顯式地使用
extends關鍵字指明其父類,則默認父類為java.lang.Object類 Object類中的屬性和方法具有通用性
- 屬性:無
- 常用方法:
- equals()
- toString
- getClass()
- hashCode()
- …

Object類中只定義了一個空參的構造器
equals()
- 回顧
==的使用
==是一個運算子,可以使用在基本資料型別變數和參考資料型別的變數中- 如果比較的是基本資料型別變數,則比較兩個變數保存的資料是否相等(不一定型別相同)
- 如果比較的是參考資料型別變數,則比較兩個物件的地址值是否相同,即比較
兩個參考是否指向同一個物件物體==使用時,必須保證符號左右兩邊的變數型別“一致”
- equals()
equals()是一個方法,而非運算子- 只適用于參考資料型別
Object類中equals()的定義:與==作用相同,即比較兩個物件的地址值是否相同
// Object原始碼中equals()的實作
public boolean equals(Object obj) {
return (this == obj);
}
String、Date、File、包裝類都重寫了Object的equals()方法,重寫之后,比較的不再是兩個參考的地址是否相同,而是比較兩個物件**物體內容(屬性)**是否相同
- 通常情況下,我們自定義的類如果使用
equals()方法時,比較的也是類中物體內容是否相同,因此需要重寫Object類中的equals()方法
重寫規則:比較兩個物件的物體內容是否相同

// String原始碼中equals()的實作:重寫
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length; // String底層是char[]
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
開發程序中,一般不會手撕
equals(),而是使用IDE自動生成
public class EqualsTest {
String name;
int age;
// IDE自動生成
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EqualsTest other = (EqualsTest) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
==和equals()的區別

toString()
- 當我們輸出一個物件的參考時,實際上就是呼叫當前物件的
toString()方法 Object中toString()方法的定義
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
String、Date、File、包裝類都重寫了Object的toString()方法,重寫之后,使得在呼叫toString()方法時,回傳物件的**物體內容(屬性)**資訊
// String中對于toString的重寫
/**
* This object (which is already a string!) is itself returned.
*
* @return the string itself.
*/
public String toString() {
return this;
}
- 自定義類也可以重寫
toString()方法以回傳物件的物體資訊,當然也可以通過IDE生成
public class ToStringTest {
String name;
int age;
// IDE自動生成
@Override
public String toString() {
return "ToStringTest [name=" + name + ", age=" + age + "]";
}
}
單元測驗
build path→add libraries→JUnit 4- 創建Java類進行單元測驗
- 類是
public的, - 類提供公共的無參構造器
- 在此類中宣告單元測驗的方法
- 方法的權限是
public - 回傳值為
void - 方法沒有形參
- 單元測驗方法之上需要宣告注解:
@Test,并在測驗類中匯入org.junit.Test - 宣告好單元測驗方法之后,就可以在方法體內測驗相關代碼
- 寫完代碼之后,左鍵雙擊選中單元測驗方法名,右鍵
run as -> JUnit Test
說明:
- 如果執行結果沒有例外:綠條
- 如果執行結果出現例外:紅條
包裝類
- 八種基本資料型別都定義了相應的參考型別,稱之為包裝類,
為什么引入包裝類?
為了使基本資料型別的變數具有類的特征
對應關系如下

- 基本資料型別、包裝類、String三者之間的相互轉換
- 基本資料型別–>包裝類:自動裝箱/呼叫包裝類的構造器
- 包裝類–>基本資料型別:自動拆箱/呼叫包裝類
Xxx的xxxValue()方法 - 基本資料型別/包裝類–>String型別 :
- 連接運算
- 呼叫String類中多載的
valueOf(Xxx xxx)方法
- String型別–>基本資料型別/包裝類:呼叫包裝類中的
parseXxx()方法

- 自動裝箱與自動拆箱
JDK 5.0新特性
- 自動裝箱:基本資料型別->包裝類
- 自動拆箱:包裝類->基本資料型別
int m = 10;
Integer j = m; // 自動裝箱
Integer i = new Integer(10);
int n = i; // 自動拆箱
- 練習
@Test
public void test1() {
Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1); // (1)
}
@Test
public void test2() {
Object o2;
if (true) {
o2 = new Integer(1);
} else {
o2 = new Double(2.0);
}
System.out.println(o2); // (2)
}
@Test
public void test3() {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); // (3)
Integer m = 1;
Integer n = 1;
System.out.println(m == n); // (4)
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // (5)
}
// (1)1.0 編譯時 int 提升為 double
// (2)1
// (3)false new 出來的物件地址不一樣
// (4)true Integer 有一個static Integer cache[], 初始化存盤-128~+127的的數字, 自動裝箱時不用new
// (5)false 超過上述范圍,需要new
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/206821.html
標籤:python
上一篇:第十四天:執行緒池+執行緒工具類
下一篇:二叉樹入門
