日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于java中多态的理解,涉及到内存空间

發布時間:2025/6/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于java中多态的理解,涉及到内存空间 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

其實理解了程序在內存里如何搞,如何玩,是很爽的。

首先簡要說明下程序運行時,內存的結構。堆區棧區,常量區,靜態方法區和非靜態方法區。

1.棧:存放基本類型的變量數據和對象的引用(也就是在new對象時左邊那一塊),但是對象本身不放在棧中,而是存在堆(new出來的對象)。棧中的數據大小和生命周期是可以確定的,當沒有引用指向數據時,這個數據就會消失。

2.堆:存放new出來的對象。堆中的對象由垃圾回收器負責回收,因此大小和生命周期不需要確定。

3.常量區:存放字符串常量和基本類型常量。


代碼示例:

[java]?view plaincopy
  • <span?style="font-family:Microsoft?YaHei;">class?Fu??
  • {??
  • ????void?method1()??
  • ????{??
  • ????????System.out.println("fu?method_1");??
  • ????}??
  • ????void?method2()??
  • ????{??
  • ????????System.out.println("fu?method_2");??
  • ????}??
  • ????static?void?method3()??
  • ????{??
  • ????????System.out.println("fu?method_3");??
  • ????}??
  • }??
  • class?Zi?extends?Fu??
  • {??
  • ????void?method1()??
  • ????{??
  • ????????System.out.println("zi?method_1");??
  • ????}??
  • ????void?method4()??
  • ????{??
  • ????????System.out.println("zi?method_4");??
  • ????}??
  • ????static?void??method3()??
  • ????{??
  • ????????System.out.println("fu?method_3");??
  • ????}??
  • }??
  • class?DemoDuotai??
  • {??
  • ????public??static?void?main(String?args[])??
  • ????{??
  • ????????Fu?aa=new?Zi();//創建一個父類引用,指向子類。??
  • ????????aa.method1();//發生動態綁定,打印子的??
  • ????????aa.method3();//打印父的??
  • ????}??
  • }</span>??



  • 內存圖簡要示例



    分析:

    1.我們知道類的非靜態成員函數,都是得靠類的對象來調用的,也就是所謂的this.。那么在這句

    Fu ff=new Zi();

    ff.method1();

    當我們aa.method1()-->this.method1()-->(new Zi()).method1().aa確實是指向Zi類的對象,method1()在運行時一定是被對象調用執行,而不是aa,因為他打印的時候或者訪問的時候是訪問對象中的那些數據。

    2.而靜態方法就不同了,他本身不訪問對象特有數據。當Fu類和Zi類被加載到內存的時候,靜態方法區就已經在里面啦,并且綁定在這個方法所屬的類上面了,所以他們只直接用類名可以調用,也就是所謂的靜態綁定。他找的是靜態區的方法,不參考右邊的對象。所以

    aa.method3();

    只參考這個引用型變量aa是誰的。

    總結:

    1.編譯時期:參考應用型變量所屬的類中是否有調用的方法。如果有,編譯通過,如果沒有,編譯失敗。

    2.運行時期:參考對象(new出來的對象)所屬的類中是否有調用的方法。(動態綁定)

    也就是:成員函數在多臺調用時,編譯看左邊,運行看右邊。

    3.多態中,成員變量的特點:無聊編譯運行,都參考左邊(引用型變量所屬的類)。

    4.多態中,靜態函數的特點:無聊編譯運行,都參考左邊。(靜態綁定)

    再舉個例子來說明編譯時(javac)和運行時(java)的區別,代碼如下:

    [java]?view plaincopy
  • class?Demo??
  • {??
  • ????private?int?num;??
  • ????Demo(int?num)??
  • ????{??
  • ????????this.num=num;??
  • ????}??
  • ????public?boolean?equals(Object?d)??
  • ????{??
  • ????????Demo?a=(Demo)d;??
  • ????????return?this.num==a.num;??
  • ????}??
  • }??
  • class?Person??
  • {??
  • ??
  • }??
  • public?class?object_equals??
  • {??
  • ????public?static?void?main(String[]?args)??
  • ????{??
  • ????????Demo?a=new?Demo(3);??
  • ????????Demo?b=new?Demo(4);??
  • ????????Person?c=new?Person();??
  • ????????System.out.println(a.equals(c));??
  • ????}??
  • ??????
  • }??
  • 結果:編譯通過,運行掛掉

    分析:

    equals是所有類的超類Object的方法,我們把他復寫掉,調用equals時,參數 Object d=new Person()這里發生了向上轉型,接著

    Demo a=(Demo)d 編譯的時候是不會出錯的,因為此處的d引用變量是綁定的Object這個類;而運行的時候,發生動態綁定也就綁定到了Person類上,把Person類的對象轉化成Demo類的對象,出現類型轉換錯誤。

    改正:

    加上 if(!d instanceof Demo) return ;

    判斷一下即可.

    ?多態(polymorphism):在執行期間(而非編譯器)判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。由于是在運行期的動態實現,直到new出對象才能確定具體調用的哪個方法,因此多態又叫動態綁定,也叫遲綁定。

    ?? 實現條件

    ????????????????1.類之間繼承或者實現接口;

    ??????????? 2.方法重寫;

    ??????????? 3.父類引用指向子類對象。

    ?? 練習

    ???????????????????貓、狗類實現抽象類動物的enjoy()方法,main方法中實現enjoy()方法的動態調用。

    ??????????? 代碼實現:

    abstract class Animal {private String name;Animal(String name) {this.name = name;}public abstract void enjoy(); }class Cat extends Animal {private String eyescolor;Cat(String name,String eyescolor) {super(name);this.eyescolor = eyescolor;}public void enjoy() {System.out.println("貓叫聲。。。");} }class Dog extends Animal {private String furcolor;Dog(String name,String furcolor) {super(name);this.furcolor = furcolor;}public void enjoy() {System.out.println("狗叫聲。。。");} } /* class Bird extends Animal {Bird() {super("bird");}public void enjoy() {System.out.println("鳥叫聲。。。");} } */class Lady {private String name;private Animal pet;Lady(String name, Animal pet) {this.name = name;this.pet = pet;}public void myPetEnjoy() {pet.enjoy();} }public class Test {public static void main(String[] args) {Dog g = new Dog("mydog","black");Cat c = new Cat("mycat","blue");Bird b = new Bird();Lady l1 = new Lady("l1",g);Lady l2 = new Lady("l2",c);//Lady l3 = new Lady("l3",b);l1.myPetEnjoy();l2.myPetEnjoy();//l3.myPetEnjoy();} }

    ???????????????運行結果:


    ?????????????? 內存分析:

    ?????????????????

    ?????????????stack中存放臨時變量,heap中存放new出的實例對象,為簡單起見,圖中略去了代碼中Dog類對象以及相應的l1對象。

    ??????? 多態的實現是通過調用方法為運行時動態生成的Cat對象指向的Cat:enjoy()方法實現。

    特性:

    ??????? 多態的存在能夠更好的讓我們去實現代碼的可擴展性(具體練習中可將Bird類、main方法的注釋去掉,則會在無需修改其他類的情況下實現鳥叫聲的擴展),大大提高了我們程序的靈活性。

    總結:

    ????????多態在之前已有過學習,但理解并不是深入,通過這次學習的相應內存分析,還是深刻了很多,對內存也有過一些了解,但之前并沒有將這兩方面的學習聯系起來,分析內存對程序的運行過程有了進一步的了解。


    總結

    以上是生活随笔為你收集整理的关于java中多态的理解,涉及到内存空间的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。