一、簡介
描述:
- 多型性是面向物件編程中的一個重要特性,主要是用來實作動態聯編的,換句話說,就是程式的最終狀態只有在執行程序中才被決定,而非在編譯期間就決定了,這對于大型系統來說能提高系統的靈活性和擴展性,
- 多型允許相同類域的不同物件對同一訊息做出回應,即同一訊息可以根據發送物件的不同而采用多種不同的行為方式,
- 多型可以讓我們不用關心某個物件到底是什么具體型別,就可以使用該物件的某些方法,從而實作更加靈活的編程,提高系統的可擴展性,
- 如果物件的編譯時型別和運行時型別不一致,就會造成多型,
存在條件:
- 類之間有繼承關系,
- 子類重寫父類方法,
- 父類參考指向子類物件,
注意:
- 多型是方法的多型,屬性沒有多型性,
- 一個物件的實際型別是確定的,但是可以指向這個物件的參考的型別,卻是可以是這物件實際型別的任意父型別,
- 子類繼承父類,呼叫方法,如果該方法在子類中沒有重寫,那么就是呼叫的是子類繼承父類的方法,如果重寫了,那么呼叫的就是重寫之后的方法,
- 'protected'修飾的父類方法可以被子類見到,也可以被子類重寫,但是它是無法被外部所參考的,所以沒有多型性,
- 通過一個變數呼叫其參考的物件的一個方法,編譯器是否能讓其編譯通過,主要是看該變數型別的類中有沒有定義該方法,如果有則編譯通過,如果沒有則編譯報錯,而不是看這個變數所參考的物件中有沒有該方法,
- Java中的方法呼叫,是運行時動態和物件系結的,不到運行的時候,是不知道到底哪個方法被呼叫的,
- 撰寫程式時,如果想呼叫運行時型別的方法,只能進行型別轉換,不然通不過編譯器的檢查,但是如果兩個沒有關聯的類進行強制轉換,會報型別轉換例外:ClassCastException,
示例:
public class Test {
public static void main(String[] args) {
/* 編譯看左,運行看右 */
Student student = new Student();
/* 變數person是可以指向Person型別或其子型別的物件,所以可以指向Student型別物件 */
Person person = new Student();
/* 變數student能呼叫的方法是Student類中有的方法(包括繼承過來的) */
student.say();//Student
/* 變數person能呼叫的方法是Person類中有的方法 */
person.say();//Student
}
}
class Person {
public void say() {
System.out.println("Person");
}
}
class Student extends Person {
public void say() {
System.out.println("Student");
}
}
二、重寫、多載、多型的關系
- 多載是編譯時多型
- 呼叫多載的方法,在編譯期間就要確定呼叫的方法是誰,如果不能確定則編譯報錯 ,
- 重寫是運行時多型
- 呼叫重寫的方法,在運行期間才能確定這個方法到底是哪個物件中的,
- 重寫方法所屬取決于呼叫方法的參考,在運行期間所指向的物件是誰,那么呼叫的就是該物件中的方法,
三、方法系結
- 程式執行呼叫方法時,系統根據相關資訊,能夠執行記憶體地址中代表該方法的代碼,
- 根據系結方法的代碼的時機不同,分為靜態系結和動態系結,
靜態系結:
- 在編譯期完成,可以提高代碼執行速度,
動態系結:
- 通過物件呼叫的方法,采用動態系結機制,
- 這雖然讓我們編程靈活,但是降低了代碼的執行速度,
- Java所有方法都是JVM在運行期才進行動態系結的,
四、'instanceof'關鍵字
描述:
- 'instanceof'是Java的一個二元運算子,
- 'instanceof'是Java的保留關鍵字,
- 'instanceof'的作用是測驗它左邊的物件是否是它右邊的類的實體,回傳一個布林值,
注意:
- 'instanceof'左邊的參考的型別與右邊的類之間,必須有父子關系或子父關系,否則編譯會報錯,
- 'instanceof'的布林值結果,根據左邊的參考的物件型別是否為右邊的類的子型別,
示例:
public class Test {
public static void main(String[] args) {
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
}
}
class Person {
}
class Student extends Person {
}
class Teacher extends Person {
}
五、型別轉換
描述:
- 由于多型的關系,父類參考可以指向子類物件,子類參考不能指向父類物件,當我們想要呼叫子類中的方法,而物件的參考型別是其父類時,就需要將該參考型別進行強制型別轉換,
- 把子類物件直接賦給父類參考叫向上轉型,向上轉型不用進行強制型別轉換,
- 把指向子類物件的父類參考賦給子類參考叫向下轉型,需要進行強制型別轉換,
- 向上轉型會丟失子類特有的方法,但是子類若重寫了父類的方法,重寫的子類方法仍有效,
- 向上轉型可以減少重復代碼,體現了抽象編程的思想,父類參考作為形式引數,調有時用子類參考作為實際引數,就是利用了向上轉型,
強制型別轉換語法:
(targetType) object
示例:
public class Test {
public static void main(String[] args) {
Person person1 = new Student();
Student student1 = (Student) person1;
student1.go();//studentGo
student1.run();//studentRun
person1.run();//studentRun
Object object1 = new Student();
Person person2 = (Person) object1;
person2.run();//studentRun
/*
因為object2參考的物件型別不是Student的子型別,所以以下代碼會出現運行時例外:ClassCastException
Object object2 = new Teacher();
Student student2 = (Student) object2;
*/
}
}
class Person {
public void run() {
System.out.println("personRun");
}
}
class Student extends Person {
public void run() {
System.out.println("studentRun");
}
public void go() {
System.out.println("studentGo");
}
}
class Teacher extends Person {
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/227884.html
標籤:其他
上一篇:pycharm 完成pull,push,建立分支更新github代碼
下一篇:Spring事務總結
