天天看点

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是指向的子类对象)。

综述:多态的优势就是面向接口编程。