天天看點

java多态記憶體分析

      “  時針如果可以回頭,熟悉那張臉,重溫嬉戲這樂園,牆壁的松脫塗鴉已經褪色才明白存在的價值歸于記憶。街角小店尚存在嗎?這大時代會不會牽挂,過去現在花開怎麼會等待。

      但有種意外不管痛不痛都有傷害,光陰遠遠離開,那笑聲徘徊與腦海。但這一秒可笑不再可愛,當天心跳不在。

    時針如果可以暫停,能否去改變曾經演過的劇情,電影般改變的情節要删去的就随着歲月 消聲 去迹。高貴的美酒和上湯,比不上家裡親切的小菜,太痛恨當天不懂得去忍耐。但這種意外,即使悔改免不了傷害。光陰遠遠離開,那痛楚徘徊于腦海,痛失所愛,錯過以後有沒有”

這是最近看的電影的一部主題曲,诶,時間啊、命運啊、輪回。這時候說什麼努力就好,注重過程不在乎結果這樣的話是空洞的。可能就是曲折和心酸才讓人刻骨銘心啊。平凡的我,在茫茫IT大軍裡顯得多麼微不足道,但是還是要向前看!

    進入主題:既然是多态,那麼先說說java多态的三個條件:

                      1、存在繼承

                       2、父類引用指向子類對象

                      3、有方法的重寫

     條件1,繼承。說到繼承可以繼承一個普通的類,也可以繼承抽象類,甚至是implements接口。現在就着重講一下,抽象類和接口。

     看代碼

public class Animal{
	    public void run(){
		
		}
	}
class Cat extends Animal{
      public void run(){
   
   }
 }
           

 Cat繼承Animal,考慮到很多的類都會繼承Animal并且重寫run方法,這時要把父類聲明為抽象類,并且把run方法定義為抽象的方法

public abstract class Animal{

  public abstract void run();

 }

子類必須要按照規範來實作父類的方法。抽象類提供了模版

 抽象類也可以定義普通的方法

public abstract class Animal{
	 public abstract void run();
	 public  void breath(){
	 }
	}
           

 增加了一個呼吸方法

問?能否在抽象類的普通方法裡面調用抽象方法呢?

比如

public abstract class Animal{
	 public abstract void run();
	 public  void breath(){
	 run();
	 }
	}
           

 答案:可以,因為實作抽象的類是一個具體的類,必定實作了run()方法。

抽象類可以包含屬性方法構造函數,但是不能被執行個體化,但是可以作為一個引用類型,引用子類的對象。

 抽象類存在的意義就是被子類繼承,因為抽象類不能執行個體化,要用隻有子類來用。将方法的設計和實作分離開來。

 抽象類裡有實作,還不夠簡單,為了進一步地抽象,引入了接口,Interface。

 接口中隻有常量(public static final)和抽象方法(public abstract),是不變的東西,這就是規範,這就是java開發軟體的優勢

這樣說有點抽象,取一個實際的例子。

飛機,石頭,籃球這些相似度很低的東西,我們發現使用繼承都不夠用了,于是用接口來描述它們的特性(會飛,有攻擊力)

定義接口

public Interface flyable{//
會飛	   void fly();
	}
	public Interface attacktion{
//可以攻擊	   void attack();
	}
           
class fly implements flyable,attackion{
	 public  void  fly(){
	 Syso("飛機飛");
	 }
	 public void attack(){
	 Syso(“開火攻擊”);
	 }
	 }
	 
	 class stone implements flyable{
	 public  void  fly(){
	 Syso("石頭被人丢着飛");
	 }
           

  接口已經夠簡單了,一個類可以繼承多個接口。

繼承時的記憶體分析: 比如

  繼承關系如下 Object(toString()方法)——Animal(run方法,動物都可以動)——Bird(鳥是動物裡面的一種,重寫run方法,可以飛) 

  現在在main方法裡 Bird bird=new Bird();

  它的記憶體情況如下:Bird bird;就如同與 int a;引用變量在棧區,都是四個位元組,假設在bird的值為a04ab233

  執行new Bird(),在堆區生成一個對象,并且給成員初始化,同時成員方法的隐式參數super會去通路父類。也就是通路Animal裡面的構造函數,run方法,最後Animal類的成員方法通過 隐式參數super通路父類 Object裡的方法toString(),equals 等等。

繼承就是這些了。

條件2:父類的引用指向子類的對象

此時父類引用調用重寫的run方法,會直接地調用子類方法的語句,而不是父類的run方法,當然父類的run方法依舊存在,當引用執行父類對象就會調用父類的run方法了。

小例子讓你了解:

  多态為什麼使用父類的引用指向子類的對象比如 Animal a=new Bird();執行 a.run();方法會執行鳥的run方法裡的語句,

  原因是:對象是子類的對象,隻是引用變量用了父類的,實際的内容都是子類的啊,就比如你用一個普通背包裝着一部acer的電腦,和用一個專用的電腦包裝着這部電腦一樣,内容都是這個電腦。

  結合記憶體分析:

  是以在java裡面強制類型轉換都是由高到低的轉換。同一個等級的不同類不能強制類型轉換報classcastException,低等級不能向高等級轉換(除非出現 Animal a=new Bird(), Bird b=(Bird)a。因為

  a是指向的子類對象)。

綜述:多态的優勢就是面向接口程式設計。