多態性,是面向對象中最重要的概念,在java中有兩種體現:java
方法的重載(overload)和重寫(overwrite)。對象
對象的多態性——能夠直接應用在抽象類和接口上。繼承
java引用變量有兩個類型:編譯時類型和運行時類型。編譯時類型由聲明該變量時使用的類型決定,運行時類型由實際賦給該變量的對象決定。接口
若編譯時類型和運行時類型不一致,就出現多態(polymorphism)。內存
對象的多態,在java中,子類的對象能夠替代父類的對象使用it
一個變量只能有一種肯定的數據類型。編譯
一個引用類型變量可能指向(引用)多種不一樣類型的對象。ast
Person p = new Student();//Person類型的變量p,指向Student類型的對象。變量
子類可看作是特殊的父類,因此父類類型的引用能夠指向子類的對象:向上轉型(upcasting)(子類的對象能夠被父類的引用變量使用)。數據類型
一個引用類型變量若是聲明爲父類的類型,但實際引用的是子類對象,那麼該變量就不能再訪問子類中添加的屬性和方法。
Student m = new Student();
m.school = "pku"; //合法,Student類有school成員變量
Person e = new Student();
e.school = "pku"; //非法,Person類沒有school成員變量
屬性是在編譯時肯定的,編譯時e爲Person類型,沒有school成員變量,因此編譯錯誤。
虛擬方法調用
編譯時e爲Person類型,而方法的調用是在運行時肯定的,因此調用的是Student類的方法。
java的方法時運行在棧內存中的,運行方法時會動態進棧和出棧。
多態小結
前提:須要存在繼承或實現關係。要有覆蓋操做。
成員方法:成員方法的多態性,也就是動態綁定,必須得存在與方法的重寫之上。
編譯時:要查看引用變量所屬的類中是否有所調用的方法。
運行時:調用實際對象所屬的類中的重寫方法。
成員變量:不具有多態性,只看引用變量所屬的類。
子類繼承父類
若子類重寫了父類方法,就意味着子類裏定義的方法完全覆蓋了父類裏的同名方法,系統將不可能把父類裏的方法轉移到子類中。
對於實例變量則不存在這樣的現象,即便子類裏定義了和父類徹底相同的實例變量,這個實例變量依然不可能覆蓋父類中定義的實例變量。
多態性應用舉例
方法聲明的形參類型爲父類類型,能夠使用子類的對象做爲實參調用該方法。