亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談Java繼承中的轉(zhuǎn)型及其內(nèi)存分配

 更新時間:2017年11月14日 09:53:34   作者:超超boy  
這篇文章主要介紹了淺談Java繼承中的轉(zhuǎn)型及其內(nèi)存分配,首先分享了簡單的代碼及運(yùn)行結(jié)果,然后對其進(jìn)行分析,繼而引出了

看書的時候被一段代碼能凌亂啦,代碼是這樣的:

package 繼承;
abstract class People
  {
    public String tag = "瘋狂Java講義";     //①
    public String name = "Parent";
    String getName(){
      return name;
    }
  }
  class Student extends People
  {
    //定義一個私有的tag實(shí)例變量來隱藏父類的tag實(shí)例變量
    String tag = "輕量級Java EE企業(yè)應(yīng)用實(shí)戰(zhàn)";     //②
    public String name = "Student";
  }
  public class HideTest2
  {
    public static void main(String[] args)
    {
      Student d = new Student();
      //將d變量顯式地向上轉(zhuǎn)型為Parent后,即可訪問tag實(shí)例變量
      //程序?qū)⑤敵觯骸隘偪馢ava講義”
      System.out.println(((People)d).tag);     //④
      System.out.println(d.getName()); //parent
    }
  }

運(yùn)行結(jié)果:

瘋狂Java講義
Parent

在這個代碼中,抽象父類People定義了兩個變量和一個getName()方法,子類student也定義了兩個和父類同名的變量,把父類的隱藏。

關(guān)于這段代碼的兩個困惑:1.子類實(shí)例化時必須首先實(shí)例化父類對象,而父類是抽象類,不能有對象。那到底子類實(shí)例化時產(chǎn)不產(chǎn)生父類對象???

2.d.getName();//返回的是parent,而不是student.不應(yīng)該把父類的隱藏么??

書中是這么解釋的:

Student對象會保存兩份實(shí)例變量,一份是people中定義的實(shí)例變量,一份是Student中定義的實(shí)例變量,d變量引用一個Student對象,內(nèi)存示意圖如下:

將d向上轉(zhuǎn)型為Parent對象,在通過它訪問name變量是允許的,也就是輸出“parent”。

但看著他的解釋還是有點(diǎn)不明白,說的不是很清楚,又去網(wǎng)上搜了下:

java子類實(shí)例化時是否同時存在一個父類對象.

假如父類A中有個inta=1;

子類B繼承A,同時B中覆蓋個inta=2;

運(yùn)行:

Atest=newB();

system.out.println(test.a);

結(jié)果是1,是父類中的屬性.這個時候是否存在父類對象,我的理解是存在的.

我又試,把父類用抽象abstract修飾,按理說abstract累不能實(shí)例化吧,肯定不能得到父類中的a屬性,結(jié)果還是一樣的.

怎么理解.

問題補(bǔ)充:

是不是創(chuàng)建子類對象,肯定會出現(xiàn)一個父類的對象?

精彩回答

不會產(chǎn)生父類對象,只是用了父類的構(gòu)造函數(shù)而已,并不是用到構(gòu)造函數(shù)就會產(chǎn)生對象,構(gòu)造函數(shù)只是起對象初始化作用的,而不是起產(chǎn)生對象作用的,如果newA();即只有new語句才會產(chǎn)生父類A的對象。

變量是靜態(tài)綁定,方法是動態(tài)綁定。這里面變量在編譯期間實(shí)現(xiàn)了變量調(diào)用語句與變量定義賦值語句的綁定,綁定的自然是父類的,因?yàn)檎{(diào)用時類型是父類的,所以值是父類中定義的值

其實(shí)你可以這么理解創(chuàng)建了一個子類對象時,在子類對象內(nèi)存中,有兩份這個變量,一份繼承自父類,一份子類。

絕對不會產(chǎn)生父類對象,父類中的成員被繼承到子類對象中,用指向子類對象的父類引用調(diào)用父類成員,只不過是從子類對象內(nèi)存空間中找到那個被繼承來的父類成員,也就是說實(shí)質(zhì)是用子類對象調(diào)用變量a,這樣就可以解釋成員必須通過對象調(diào)用的規(guī)定,只不過這時調(diào)用的是子類對象中的繼承自父類的a(子類對象中有兩個a,一個繼承自父類,一個屬于自己)

哎,話說的有些亂。這個問題也困惑我很久,上網(wǎng)查詢發(fā)現(xiàn)很多人是錯誤的,最后找到幾篇好的文章才明白,可能很多java老手也都會犯“產(chǎn)生父類對象”這個錯誤,最近才搞明白。

你自己想想,如果產(chǎn)生父類對象,如果父類是抽象類,抽象類允許產(chǎn)生對象嗎?所以這種說法不嚴(yán)謹(jǐn)

動態(tài)綁定定義

動態(tài)綁定是指在執(zhí)行期間(非編譯期)判斷所引用對象的實(shí)際類型,根據(jù)其實(shí)際的類型調(diào)用其相應(yīng)的方法

靜態(tài)綁定與動態(tài)綁定

除了限制訪問,訪問方式也決定哪個方法將被子類調(diào)用或哪個屬性將被子類訪問.函數(shù)調(diào)用與函數(shù)本身的關(guān)聯(lián),以及成員訪問與變量內(nèi)存地址間的關(guān)系,稱為綁定.

在計(jì)算機(jī)語言中有兩種主要的綁定方式,靜態(tài)綁定和動態(tài)綁定.靜態(tài)綁定發(fā)生于數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)間,程序執(zhí)行之前.靜態(tài)綁定發(fā)生于編譯期,因此不能利用任何運(yùn)行期的信息.

它針對函數(shù)調(diào)用與函數(shù)的主體,或變量與內(nèi)存中的區(qū)塊..動態(tài)綁定則針對運(yùn)行期產(chǎn)生的訪問請求,只用到運(yùn)行期的可用信息.在面向?qū)ο蟮拇a中,動態(tài)綁定意味著決定哪個方法被調(diào)用或哪個屬性被訪問,

將基于這個類本身而不基于訪問范圍.

子類在創(chuàng)建實(shí)例后,類初始化方法會調(diào)用父類的初始化方法(除了java.lang.Object類,因?yàn)閖ava.lang.Object類沒有父類),而這種調(diào)用會逐級追述,直到j(luò)ava.lang.Object的初始化方法。

這個地方我說的是初始化方法,而不是構(gòu)造方法,因?yàn)闃?gòu)造方法是相對于java源程序而言,而編譯后的class文件是初始化方法即"<init>"方法(紅色部分為方法名),

初始化方法是由java源程序的三個部分組成的,一個部分是成員字段后的直接的初始化語句,例如privateinti=0;privateDatedate=newDate();等等,第二個部分是由初始化塊組成,例如:

Javacode

publicclassTest{

privateinti=0;//初始化第一部分

//以下大括號內(nèi)為初始化第二部分

{this.i=4;//dosomething......}}

第三個部分就是java源代碼中的構(gòu)造方法中的代碼,java源代碼中有幾個構(gòu)造方法,那么class文件中就有幾個初始化方法,編譯器會把第一部分與第二部分分別復(fù)制到每個初始化方法的前端,然后把初始化

方法對應(yīng)參數(shù)的構(gòu)造方法的代碼復(fù)制到相應(yīng)初始化方法中(這里說的復(fù)制其實(shí)應(yīng)該說是編譯,不過為了讓你更好理解所以如此說).

那么說初始化方法如何追述其父類的,這也關(guān)系到初始化方法的結(jié)構(gòu),初始化方法的執(zhí)行順序以及結(jié)構(gòu)就如上所說,但是每個初始化方法的第一個執(zhí)行指令就是調(diào)用另外一個初始化方法,

這個初始化方法可能是自身類某個初始化方法,例如你的構(gòu)造函數(shù)中第一句有類似this(...)這種語句,那么初始化方法就會調(diào)用自身類的指定構(gòu)造方法;如果你的構(gòu)造方法中沒有指定構(gòu)造方法調(diào)用,

那么初始化方法會默認(rèn)調(diào)用父類無參數(shù)初始化方法,如果你的子類第一句為super(....),那么初始化方法會調(diào)用父類指定初始化方法。這種調(diào)用過程會遞歸進(jìn)行調(diào)用,直到這個類是java.lang.Object類。

調(diào)用初始化方法并不代表會生成對象,你的java代碼中出現(xiàn)new關(guān)鍵字加上構(gòu)造方法的調(diào)用,只會生成一個對象,其父類對象不會生成,所以調(diào)用父類為抽象類的構(gòu)造方法完全是合理的。

而且初始化方法對于虛擬機(jī)來說只是一個名稱叫做"<init>"的普通方法,區(qū)別只是生成對象以后調(diào)用而已(sun的jdk私有包中有繞過構(gòu)造方法生成對象的方式,可以證明之上說法,具體如何我這里不陳述)。

然后回答你的第二個問題,抽象類中的構(gòu)造方法其實(shí)是用來給繼承的子類來用的,因?yàn)闃?gòu)造方法相當(dāng)于初始化方法,當(dāng)子類調(diào)用構(gòu)造方法時必須調(diào)用父類構(gòu)造方法,

所以你可以在子類產(chǎn)生對象時抽象類中按需求初始化抽象類中的字段以及執(zhí)行一些初始化代碼。其實(shí)并不是一定要生成某個類的實(shí)例才調(diào)用構(gòu)造方法,子類也需要調(diào)用父類構(gòu)造方法。

而生成實(shí)例也并不一定會調(diào)用構(gòu)造方法,在某些特殊實(shí)現(xiàn)中或者特殊情況下,生成實(shí)例不會調(diào)用構(gòu)造方法。而調(diào)用了構(gòu)造方法也不一定就生成了一個實(shí)例,但是那一定是一個實(shí)例調(diào)用的,就像一個普通的實(shí)例方法一樣。

總結(jié)

以上就是本文關(guān)于淺談Java繼承中的轉(zhuǎn)型及其內(nèi)存分配的全部內(nèi)容,希望對大家有所幫助,感興趣的朋友可以繼續(xù)參閱本站:Java編程之繼承問題代碼示例Java面向?qū)ο缶幊蹋ǚ庋b/繼承/多態(tài))實(shí)例解析等,有什么問題可以隨時留言,小編會及時回復(fù)大家的。感謝朋友們對本站的支持!

相關(guān)文章

  • 一篇文章讓你三分鐘學(xué)會Java枚舉

    一篇文章讓你三分鐘學(xué)會Java枚舉

    這篇文章主要給大家介紹了如何通過三分鐘學(xué)會Java枚舉的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • SpringBoot項(xiàng)目docker容器部署實(shí)現(xiàn)

    SpringBoot項(xiàng)目docker容器部署實(shí)現(xiàn)

    本文主要介紹了SpringBoot項(xiàng)目docker容器部署實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • 零基礎(chǔ)寫Java知乎爬蟲之將抓取的內(nèi)容存儲到本地

    零基礎(chǔ)寫Java知乎爬蟲之將抓取的內(nèi)容存儲到本地

    上一回我們說到了如何把知乎的某些內(nèi)容爬取出來,那么這一回我們就說說怎么把這些內(nèi)容存儲到本地吧。
    2014-11-11
  • java.net.UnknownHostException異常的一般原因及解決步驟

    java.net.UnknownHostException異常的一般原因及解決步驟

    關(guān)于java.net.UnknownHostException大家也許都比較熟悉,這篇文章主要給大家介紹了關(guān)于java.net.UnknownHostException異常的一般原因及解決步驟,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • RabbitMQ?延遲隊(duì)列實(shí)現(xiàn)訂單支付結(jié)果異步階梯性通知(實(shí)例代碼)

    RabbitMQ?延遲隊(duì)列實(shí)現(xiàn)訂單支付結(jié)果異步階梯性通知(實(shí)例代碼)

    這篇文章主要介紹了RabbitMQ?延遲隊(duì)列實(shí)現(xiàn)訂單支付結(jié)果異步階梯性通知,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • Java中的TreeSet集合詳解

    Java中的TreeSet集合詳解

    這篇文章主要介紹了Java中的TreeSet集合詳解,TreeSet 是一個 有序集合,它擴(kuò)展了 AbstractSet 類并實(shí)現(xiàn)了 NavigableSet 接口,作為自平衡二叉搜索樹,二叉樹的每個節(jié)點(diǎn)包括一個額外的位,用于識別紅色或黑色的節(jié)點(diǎn)的顏色,需要的朋友可以參考下
    2023-09-09
  • 淺析Java中的動態(tài)代理

    淺析Java中的動態(tài)代理

    動態(tài)代理指代理類和目標(biāo)類的關(guān)系在程序運(yùn)行的時候確定的,客戶通過代理類來調(diào)用目標(biāo)對象的方法。本文將通過案例詳細(xì)講解一下Java動態(tài)代理的原理及實(shí)現(xiàn),需要的可以參考一下
    2022-09-09
  • Mybatis實(shí)現(xiàn)自動生成增刪改查代碼

    Mybatis實(shí)現(xiàn)自動生成增刪改查代碼

    這篇文章主要為大家詳細(xì)介紹了Mybatis如何實(shí)現(xiàn)自動生成增刪改查代碼的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-01-01
  • SpringBoot實(shí)現(xiàn)MapperScan添加動態(tài)配置(占位符)

    SpringBoot實(shí)現(xiàn)MapperScan添加動態(tài)配置(占位符)

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)MapperScan添加動態(tài)配置(占位符),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • Java日期時間操作的方法

    Java日期時間操作的方法

    這篇文章主要為大家詳細(xì)介紹了Java日期時間操作的一些方法,獲得Calendar,定義日期/時間的格式等,感興趣的小伙伴們可以參考一下
    2016-08-08

最新評論