多态
- 定義
- 注意
- 調用的屬性與方法差別
- 多态用途
- 父子類之間的類型轉換
- instanceof
- native 本地的
- Object 類
- ==号與equals方法
- 接口
定義
定義:同一行為,具有多個不同的表現形式
前提:父子類或接口實作,必須有重寫,父類引用指向子類對象。
注意
注意:
是用不了子類獨有的内容,
因為名義是父類的類型,隻能調用父類存在的,如果子類有重寫父類的方法,則可以調用重寫的方法。
調用的屬性與方法差別
變量看類型,方法看對象。
Person per1 = new Student();
per1.name; // 這個是父類的,因為屬性定義是在父類對象的,即便重寫了也是父類的
per1.study(); // 方法的實際對象是子類對象,調用者是實際的子類對象
多态用途
多态參數:
用父類作為方法的參數,以便能夠傳遞所有的子類對象。
以下調用method方法,等價于:
Person person = employee;
public class Test {
public static void main(String[] args) {
Employee employee = new Employee();
method(employee);
Student student = new Student();
method(student);
}
public static void method(Person person){
person.eat();
}
}
多态數組:
用父類數組引用來接收子類數組對象,避免代碼重複。
以下代碼,兩者是差不多的。
Employee[] employees = new Employee[5];
Student[] students = new Student[5];
Person[] people = new Person[10];
people[0] = new Student();
people[1] = new Employee();
父子類之間的類型轉換
1,自動轉換(向上轉型 就是多态) 小 --> 大
2,強制轉換(向下轉型) 大 --> 小
與以下代碼類似:
double d = 1.0;
int i = (int)d;
想要調用子類特有的屬性或方法。
文法:
子類類型 對象名 = (子類類型)父類引用;
Person person = new Employee();// 或者這樣,Person person = new Person();,明顯這樣轉型再向下轉型不合适。
Employee employee = (Employee)person;// 這樣就可以調用Employee的是以屬性方法了。
// 如下代碼會在編譯時通過,但運作報錯
Person person = new Employee();
Student student = (Student)person;
報錯内容如下:
java.lang.ClassCastException:
對象指向錯誤,一類常見錯誤,因為父類指向了錯誤的子類導緻。
避免方法:
instanceof
判斷前面的對象是否屬于後面的類型或者是後面類型的子類。
boolean flag = employee instanceof Person;
System.out.println(flag);
flag = student instanceof Person;
System.out.println(flag);
應用,編寫函數,傳入子類對象,判斷屬于哪個子類,并調用對應對象的特殊方法。
Student student = new Student();
method(student);
Employee employee1 = new Employee();
method(employee1);
public static void method(Person person){
if(person instanceof Employee){
((Employee) person).working();
}else if(person instanceof Student){
((Student) person).studying();
}
}
注意程式設計規範,盡量不要使用轉型。聲明時可以使用自己對象類型的對象指向自己類型的空間。
調用方法時,使用父類作為參數,在傳遞時會自動向上轉型(多态)。
native 本地的
隻能修飾方法,一般追蹤源碼的時候會看到,用C寫的代碼,但可以用Java調用,native修飾的方法可以被重寫。
Object 類
Object類作為Java的根類,它的方法在繼承後可以重寫。
toString()的重寫
可以傳回一段描述你寫的類的基本情況的字元串,在
System.out.println()函數中,如果有類的對象直接在裡面,調用的則是實際是該類的toString()傳回的字元串。
對于回收機制函數,當jvm調用垃圾回收機制的時候,會調用以下函數。
finalize(),任何類可以重寫該方法。
另外提一下,呼叫垃圾回收機制來回收垃圾的函數
system.gc(); 直接使用即可。
==号與equals方法
1, ==, 表示的是兩個變量的位址是否相同。
注意, 一般常量都存儲在常量池裡,它的位址是共用的。也就是說:
String string = "java";
String string2 = "java";
System.out.println(string==string2);
/** 輸出為 true
而,以下代碼跑出來的卻是 false 的:
String string = "java";
String string2 = new String("java");
System.out.println(string==string2);
/** 輸出為 false
2, equals()方法,先來看看源碼:
這是Object類的equals()方法。
public boolean equals(Object obj) {
return (this == obj);
}
發現與==的用法相同!
然後看看 String類重寫的equals源碼:這是比較String類對象的值。
public boolean equals(Object anObject) {
// 位址相同傳回true
if (this == anObject) {
return true;
}
// anObject是否是String的子類,否傳回 false
if (anObject instanceof String) {
// 将anObject類型轉換為String類型的anothorString
String anotherString = (String)anObject;
// 字元串存儲在value的字元數組中,求其長度,就是字元串的長度n
int n = value.length;
// 判斷長度是否相同
if (n == anotherString.value.length) {
// 将this的字元串指派給v1[] anotherString指派給v2[]
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;
}
接口
接口文法:
【public】 interface 接口名 { }
JDK1.8之前:
接口中的成員變量:靜态常量,必須初始化。
接口在的成員方法:公有的抽象方法,使用時必須重寫。
無:構造器,,初始化塊。
特點:
接口不能執行個體化對象
隻能作為父類(父級接口)
子類繼承父類,,,實作類實作父接口
實作類實作父接口,并且實作父接口的所有的抽象方法
public class Aircraft implements Fly{ 抽象方法實作 }
一個類隻能有一個類,但可以有多個接口
關系:
類與類之間: 單繼承
類與接口之間:多實作
接口與接口:多繼承