Java中子類和父類相關方法的執行順序
無意中看到下面一個題目,大家一起來看看最後的輸出結果是什麼。反正我看完之後,用IDE測試後感覺知識點得到鞏固了。
1 /** 2 * 函式執行順序測試 3 * Created by 萌小Q on 2017/5/17 0017. 4 */ 5 public class ExeSeqTest { 6 7 public static void main(String [] args){ 8 System.out.println(new B().getValue()); 9 } 10 static class A{ 11 protectedint value; 12 public A(int v) { 13 setValue(v); 14 } 15 public void setValue(int value){ 16 this.value = value; 17 } 18 public int getValue(){ 19 try{ 20 value++; 21 return value; 22} catch(Exception e){ 23 System.out.println(e.toString()); 24 } finally { 25 this.setValue(value); 26 System.out.println(value); 27 } 28 return value; 29 } 30 } 31 static class B extendsA{ 32 public B() { 33 super(5); 34 setValue(getValue() - 3); 35 } 36 public void setValue(int value){ 37 super.setValue(2 * value); 38 } 39 } 40 }
執行結果:
22 34 17View Code
你們答對了麼?哈哈,現在來看一下程式碼具體執行情況:
1、首先是main方法,new了一個B物件,然後就是呼叫該物件的getValue()方法
2、執行B類的構造方法
3、執行B類構造方法裡面的super方法,即執行B的父類A的構造方法。
4、接下來就是執行setValue()方法了,但是此時A類和B類都有一個setValue()方法,到底執行哪一個呢,我一開始認為是A類的setValue()方法。
但在A類的構造方法中執行setValue()方法時,你是不是看到了,它執行的是子類B的setValue()方法。
顯然這需要鞏固一個知識點:當子類重寫了父類的函式,那麼子類的物件如果呼叫該函式,一定呼叫的是重寫過後的函式。可以通過super關鍵字進行父類的重寫函式的呼叫。
因為現在正在執行的是B類的構造方法,所以預設先會呼叫B類中的方法,如果B類中沒有,才會呼叫其父類A中的方法。
5、接下來到super.setValue(2 * value),即執行A類的setValue()方法,這時,A類的成員變數value應該就變成了10
6、這時B類的構造方法中的super(5)就執行完了,然後就到了setValue(getValue() - 3)方法
7、接著執行getValue()方法,首先在B類中找,但B類沒有getValue()方法,所以就執行A類中的getValue()方法,A類中肯定是有的,要不然編譯就不會通過
8、然後就開始執行try、catch、finally這一塊,給A的成員變數value自增,從之前的10變為11,然後直接返回value,沒有捕獲異常,繼續到finally裡面的this.setValue(value)
9、然後這個this指的到底是A類還是B類呢,答案是B類,因為現在是在執行B的構造方法,所以this指的應該是B類,即呼叫B類的setValue(int value)方法。
10、然後又super.setValue(2 * value);執行父類A的setValue(int value),把2 * 11作為引數傳遞,A類的setValue(int value)把傳進來的value值賦給了A的成員變數value,變成了22。
11、然後this.setValue(value)就執行完了,最後輸出value,22
12、到這兒getValue()方法就執行完了,但是有一點需要注意,此時的value為22,但是getValue()的返回值確是11,因為在try{ }中已經return了,所以這個方法的返回值已經儲存下來了,是11,即使finally{ }裡面又對value的值做出了改變,但是getValue()的返回值是不會變的(除了finally裡面也有return返回值,它會覆蓋前面try的返回值)。接著繼續執行B類構造方法中的setValue(getValue() - 3);getValue()是11,所以B的setValue(int value)方法的引數就為8,接著又到了super.setValue(2 * value)
13、呼叫A類的setValue(int value)方法,同時將引數賦值給A類的成員變數value,此時value變為16
14、到這兒B類的構造方法就全部執行完了,也就是new B(),然後又呼叫了該物件 的getValue()方法,B類沒有,但是父類A有,
繼續try{ }、catch{ }、finally{ },A類的成員變數value為16,然後value++,再返回,這時getValue()的返回值已經確定了,就是17,即使在finally中對value做出改變,其返回值不會變。然後到finally{ },又是this.setValue(value),前面已經說過了,這個this指的是B類的this,所以呼叫B類的setValue(int value)
接著又是super.setValue(2 * value),呼叫A類的setValue(),並把2 * 17作為引數傳遞過去
把引數賦給A的成員變數value,這時this.setValue(value)就執行完了,此時的value為34。最後輸出value。
需要注意的是,此時的getValue()方法的返回值是17,這個前面已經提到了,到這兒,整個new B().getValue()就執行完了,最後又輸出了getValue的返回值,也就是17。所以整個過程執行完後的輸出結果是22、34、17。。。。。。
這道題雖然饒了很多彎,但是我們做完後發現整體過程其實並不是很複雜,就是子類繼承父類,呼叫方法時先是呼叫子類中的方法,如果沒有就呼叫父類中的方法,還有一點就是try{ }、catch{ }、finally{ }返回值的問題,一旦try{ }中返回了某一個值,如果finally有返回值,finally中的返回值會覆蓋try的返回值,如果finally沒有返回值,就是try中的返回值。掌握了這些,這道題就顯得很簡單了。
Java初始化順序如圖:
相關推薦
Java中子類和父類相關方法的執行順序
無意中看到下面一個題目,大家一起來看看最後的輸出結果是什麼。反正我看完之後,用IDE測試後感覺知識點得到鞏固了。 1 /** 2 * 函式執行順序測試 3 * Created by 萌小Q on 2017/5/17 0017. 4 */ 5 public class ExeSeq
Java中子類和父類之間的呼叫關係
在講之前,一些基本知識是應該具備的: 1.如果一個類中沒有定義構造器,編譯器在編譯時會自動加上預設無參構造器: public ClassName {} 2. this 和 super 的區別。 3.每個類直接或間接是Object的子類,Object只有一個無參構造方法。
關於子類和父類之間的方法,構造方法呼叫關係
子類繼承了父類之後,父類的所有方法都可以被子類呼叫,父類的所有(除私有外)方法都可以被重寫; 但是父類中私有資料域不能在子類中被修改,只能通過呼叫父類的公共修改方法來修改; 例如下面圓幾何繼承了簡單幾何: 以上幾點說明: 簡單幾何類中的構造方法其實不需要寫,因
java子類和父類的執行順序
java中一個類首先是被載入到記憶體後,再去按順序執行類中的static完成初始化,在載入過程先是載入父類,在去載入子類。構建子類例項時,先建立父類的例項。執行構造方法時,先去初始化成員屬性。舉個例子說明下: class Test { public static v
靜態語句塊,非靜態語句塊,構造方法在子類和父類的執行順序
package test; public class Main { public static void main(String args[]) { new subclass();
對象序列化中 子類和父類構造函數的調用問題
images png http 分享 com 函數 對象 情況 序列 第三種情況: 對象序列化中 子類和父類構造函數的調用問題
super 子類和父類初始化例子
n) elf flag python highlight 初始 class PE bject # #重寫父類初始化 class Person(object): def __init__(self, flag=False, name="jim"):
子類和父類
article 有一個 per def -- 否則 bsp pass 了解 1. 子類沒有初始化函數, 則初始化子類的時候,需要有父類的初始化參數 Class P(object): def __init__(self,name): self.name
【轉】子類和父類實現同一個接口的意義
style inf bottom 父類 100% csdn 一個 article mage 原文作者的疑惑和我的一模一樣...所以沒什麽好解釋的,直接截圖參考即可。原文鏈接:子類和父類實現同一個接口的意義 - CSDN博客 https://blog.csdn.net/s33
關於子類和父類中的this的用法
1 public class Demo { 2 public static void main(String[] args) { 3 Fu f = new Zi(); 4 f.show(); 5 } 6 } 7 8 cla
子類和父類,靜態程式碼塊,程式碼塊呼叫順序
<![endif]--> class String ; private age { out "people static block" } System. .println( ); People() { System. .println( );
子類和父類實現同一個介面的意義
在閱讀Java.util.ArrayList原始碼的過程中,我產生了一個小疑惑,ArrayList實現了List這個介面(這沒問題,學Java的都知道),但ArrayList的抽象父類Abstrac
java中子類繼承父類和實現介面有同名方法怎麼處理
Java是一門單繼承語言,但是,在子類的繼承關係中,會存在父類和介面有同名方法的情況,這種情況該怎麼處理呢? 我們來一步步驗證: 1.子類繼承父類,實現介面,父類和介面有同名方法 public int
Java中子類與父類的構造方法
子類與父類的構造方法有兩點原則: 1、子類的構造方法必須呼叫父類的構造方法(原因為什麼,可參考此連結https://blog.csdn.net/y_dzaichirou/article/details/54920715) 2、被子類呼叫的父類構造方法必須存在(這
Java中子類重寫父類方法
子類重寫父類方法 子類可以繼承父類的很多特性,但是在有些時候,父類提供的方法會出現不適用的情況,比如之前的例子裡, print() 方法就沒有打印出狗狗的品種,這種情況下就可以通過重寫父類的方法來解決問題,給它打印出來。 父類Pet類的程式碼不需要改變,在子類Dog類的基礎上作改動即
java中多型父類的成員變數和方法呼叫問題
class Super { String name = "父類名字"; public void setName(String name) { System.out.println(this.getClass());
java中子類重寫父類方法要注意的問題
子類不能重寫父類的靜態方法,私有方法。即使你看到子類中存在貌似是重寫的父類的靜態方法或者私有方法,編譯是沒有問題的,但那其實是你重新又定義的方法,不是重寫。具體有關重寫父類方法的規則如下:重寫規則之一:重寫方法不能比被重寫方法限制有更嚴格的訪問級別。 (但是可以更廣泛,比如
java中子類繼承父類呼叫利用繼承方法時呼叫this
package cn.itcast.test1; class Parent{ public Object getObject(){ return this; } } c
Java中子類與父類的構造方法的呼叫關係
在 Java 中,無論是 explicit 還是 implicit 方式,都要求在子類的構造方法中呼叫其父類的構造方法。如果父類無構造方法(其實是一個預設無參的構造方法),那麼子類的構造方法中會自動進行呼叫;如果 父類有自己的構造方法(這時父類不會有預設無參的構造方法),那麼在子類的構造方法
java中子類覆蓋父類方法所必須滿足的條件
一、描述 子類重寫(覆蓋)父類的方法必須滿足的條件: 1.父類中的方法在子類中必須可見,即子類繼承了父類中的該方法(可以顯式的使用super關鍵字來訪問父類中的被重寫的方法), 如果父類中的方法為private型別的,那麼子類則無法繼承,也無法覆蓋。 2.子類和父類的方