程序綁定的概念:
綁定指的是一個方法的調用與方法所在的類(方法主體)關聯起來。對java來講,綁定分爲靜態綁定和動態綁定;或者叫作前期綁定和後期綁定.
靜態綁定:
在程序執行前方法已經被綁定(也就是說在編譯過程當中就已經知道這個方法究竟是哪一個類中的方法),此時由編譯器或其它鏈接程序實現。例如:C。
針對java簡單的能夠理解爲程序編譯期的綁定;這裏特別說明一點,java當中的方法只有final,static,private和構造方法是前期綁定
動態綁定:
後期綁定:在運行時根據具體對象的類型進行綁定。
若一種語言實現了後期綁定,同時必須提供一些機制,可在運行期間判斷對象的類型,並分別調用適當的方法。也就是說,編譯器此時依然不知道對象的類型,但方法調用機制能本身去調查,找到正確的方法主體。不一樣的語言對後期綁定的實現方法是有所區別的。但咱們至少能夠這樣認爲:它們都要在對象中安插某些特殊類型的信息。
動態綁定的過程:java
關於final,static,private和構造方法是前期綁定的理解
對於private的方法,首先一點它不能被繼承,既然不能被繼承那麼就沒辦法經過它子類的對象來調用,而只能經過這個類自身的對象來調用。所以就能夠說private方法和定義這個方法的類綁定在了一塊兒。
final方法雖然能夠被繼承,但不能被重寫(覆蓋),雖然子類對象能夠調用,可是調用的都是父類中所定義的那個final方法,(由此咱們能夠知道將方法聲明爲final類型,一是爲了防止方法被覆蓋,二是爲了有效地關閉java中的動態綁定)。
構造方法也是不能被繼承的(網上也有說子類無條件地繼承父類的無參數構造函數做爲本身的構造函數,不過我的認爲這個說法不太恰當,由於咱們知道子類是經過super()來調用父類的無參構造方法,來完成對父類的初始化, 而咱們使用從父類繼承過來的方法是不用這樣作的,所以不該該說子類繼承了父類的構造方法),所以編譯時也能夠知道這個構造方法究竟是屬於哪一個類。
對於static方法,具體的原理我也說不太清。不過根據網上的資料和我本身作的實驗能夠得出結論:static方法能夠被子類繼承,可是不能被子類重寫(覆蓋),可是能夠被子類隱藏。(這裏意思是說若是父類裏有一個static方法,它的子類裏若是沒有對應的方法,那麼當子類對象調用這個方法時就會使用父類中的方法。而若是子類中定義了相同的方法,則會調用子類的中定義的方法。惟一的不一樣就是,當子類對象上轉型爲父類對象時,不論子類中有沒有定義這個靜態方法,該對象都會使用父類中的靜態方法。所以這裏說靜態方法能夠被隱藏而不能被覆蓋。這與子類隱藏父類中的成員變量是同樣的。隱藏和覆蓋的區別在於,子類對象轉換成父類對象後,可以訪問父類被隱藏的變量和方法,而不能訪問父類被覆蓋的方法)
由上面咱們能夠得出結論,若是一個方法不可被繼承或者繼承後不可被覆蓋,那麼這個方法就採用的靜態綁定。
java的編譯與運行
java的編譯過程是將java源文件編譯成字節碼(jvm可執行代碼,即.class文件)的過程,在這個過程當中java是不與內存打交道的,在這個過程當中編譯器會進行語法的分析,若是語法不正確就會報錯。
Java的運行過程是指jvm(java虛擬機)裝載字節碼文件並解釋執行。在這個過程纔是真正的創立內存佈局,執行java程序。
java字節碼的執行有兩種方式: (1)即時編譯方式:解釋器先將字節編譯成機器碼,而後再執行該機器碼;(2)解釋執行方式:解釋器經過每次解釋並執行一小段代碼來完成java字節碼程序的全部操做。(這裏咱們能夠看出java程序在執行過程當中實際上是進行了兩次轉換,先轉成字節碼再轉換成機器碼。這也正是java能一次編譯,處處運行的緣由。在不一樣的平臺上裝上對應的java虛擬機,就能夠實現相同的字節碼轉換成不一樣平臺上的機器碼,從而在不一樣的平臺上運行)
前面已經說了對於java當中的方法而言,除了final,static,private
和構造方法是前期綁定外,其餘的方法所有爲動態綁定。
而動態綁定的典型發生在父類和子類的轉換聲明之下:
好比:Parent p = new Children();
其具體過程細節以下:
1:編譯器檢查對象的聲明類型和方法名。
假設咱們調用x.f(args)方法,而且x已經被聲明爲C類的對象,那麼編譯器會列舉出C 類中全部的名稱爲f 的方法和從C 類的超類繼承過來的f 方法。
2:接下來編譯器檢查方法調用中提供的參數類型。
若是在全部名稱爲f 的方法中有一個參數類型和調用提供的參數類型最爲匹配,那麼就調用這個方法,這個過程叫作「重載解析」。jvm
3:當程序運行而且使用動態綁定調用方法時,虛擬機必須調用同x所指向的對象的實際類型相匹配的方法版本。函數
假設實際類型爲D(C的子類),若是D類定義了f(String)那麼該方法被調用,不然就在D的超類中搜尋方法f(String),依次類推。佈局
JAVA 虛擬機調用一個類方法時(靜態方法),它會基於對象引用的類型(一般在編譯時可知)來選擇所調用的方法。相反,當虛擬機調用一個實例方法時,它會基於對象實際的類型(只能在運行時得知)來選擇所調用的方法,這就是動態綁定,是多態的一種。動態綁定爲解決實際的業務問題提供了很大的靈活性,是一種很是優美的機制。
與方法不一樣,在處理java類中的成員變量(實例變量和類變量)時,並非採用運行時綁定,而是通常意義上的靜態綁定。因此在向上轉型的狀況下,對象的方法能夠找到子類,而對象的屬性(成員變量)仍是父類的屬性(子類對父類成員變量的隱藏)。
Java代碼 spa
結論,調用的成員爲父親的屬性。
這個結果代表,子類的對象(由父類的引用handle)調用到的是父類的成員變量。因此必須明確,運行時(動態)綁定針對的範疇只是對象的方法。
如今試圖調用子類的成員變量name,該怎麼作?最簡單的辦法是將該成員變量封裝成方法getter形式。
代碼以下:
Java代碼 .net
結果:調用的是兒子的屬性
java由於什麼對屬性要採起靜態的綁定方法。這是由於靜態綁定是有不少的好處,它可讓咱們在編譯期就發現程序中的錯誤,而不是在運行期。這樣就能夠提升程序的運行效率!而對方法採起動態綁定是爲了實現多態,多態是java的一大特點。多態也是面向對象的關鍵技術之一,因此java是以效率爲代價來實現多態這是很值得的。
注:以上內容大部分來自互聯網,小部分是我的看法,絕非權威性言論。若有語言表達不當或者表述不正確的地方,萬望指教。code
參考:對象
http://blog.csdn.net/zhangjk1993/article/details/24066085blog