本文已参与「新人创作礼」活动,一起开启掘金创作之路。
对象实例化过程
-
对象实例化过程
- 简单类对象的实例化过程
-
注:
- 第三步开辟空间是给new Person();开辟
- 第五步构造方法进栈,指的是public Person(){}进栈,初始化指的是执行构造方法的方法体中的代码。
- 第六步将堆内存地址赋值给引用变量,即赋值给P,P存储堆中的地址
- 子类对象实例化过程
-
注:
- 第一步是先加载父类再加载子类
- 第三步开辟空间是给new Student();开辟
- 第四步对象空间即开辟的堆内存空间,默认初始化age=0,name=null,sex=0,school=null.(父类子类属性均初始化)
- 第五步子类构造方法进栈,但构造方法中又super,所以转去执行第六步显示初始化父类的属性,此时age=1,name=“zhangsan”,sex=0
- 第七步public Person(){}执行完成出栈
- 第八步显示初始化子类属性,school仍然为null
- 第九步stu存储BE3500地址
- 简单类对象的实例化过程
面向对象特征之三:多态
-
面向对象特征之三:多态
-
多态性,是面向对象中最重要的概念,在java中有两种体现:
- 方法的重载(overload)【本类中的同名方法——体现相同的名称方法实现不同的逻辑】和重写(overwrite)【子类对父类方法的覆盖——体现子类可以使用和父类相同的方法名,覆盖掉父类的逻辑。父类的方法想要修改,但有别的代码在调用父类的方法,可以考虑子类继承父类,重写父类的方法】
- 对象的多态性——可以直接应用在抽象类和接口上
-
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定
- 例如:Student stu=new Student();其中Student stu为编译时类型,new Student()为运行时类型
- 若编译时类型和运行时类型不一致,就出现对象的多态(Polymorphism)
-
对象的多态——在java中,子类的对象可以替代父类的对象使用
- 一个变量只能由一种确定的数据类型
- 一个引用类型变量可能指向(引用)多种不同类型的对象
- 举例 :Person p=new Person(); Person e=new Student();//Person类型的变量e,指向Student类型的对象
- 可以这样操作的原因:子类可看做是特殊的父类(可以看成父类的扩展),所以父类类型的引用可以指向子类的对象:向上转型(upcasting)【把子类的对象可以给父类的类型变量引用】
- 注意:一个引用类型的变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法
-
虚拟方法的调用(Virtual Method Invocation)
- 正常的方法调用
- 虚拟方法调用(多态情况下)
-
编译时类型和运行时类型
- 编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。——动态绑定
- 引用变量引用(P)那个对象,就使用该对象的方法
- 正常的方法调用
-
多态小结
-
前提
- 需要存在继承或者实现关系
- 要有覆盖操作(overload、overwrite)
-
成员方法
- 编译时:要查看引用变量所属的类中是否有所调用的方法
- 运行时:调用实际对象所属的类中的重写方法
- 注:成员方法的多态性,也就是动态绑定,必须得存在于方法的重写之上
-
成员变量(属性):
- 不具备多态性,只看引用变量所属的类
-
子类继承父类
- 如果子类没有重写父类的方法,那么子类就是直接使用父类的方法;如果重写了,子类就使用自己重写之后的方法
- 子类定义了和父类完全相同的实例变量,这个实例变量不会覆盖父类中定义的实例变量。例如:父类定义int age;子类也定义int age;不会覆盖
-
-
多态性应用举例
- 方法声明形参类型为父类类型,可以使用子类的对象作为实参调用方法
- 方法声明形参类型为父类类型,可以使用子类的对象作为实参调用方法
-
instanceof操作符
-
x instanceof A:检验x是否为A类的对象,返回值为boolean型
- 要求x所属的类与类A必须是子类和父类的关系,否则编译错误
- 如果x属于类A的子类B,x instanceof A值也为true
-
-