一、首先创建子类和父类
1.创建一个父类Person,则Person默认继承了java最底层的父类Object。
2.创建Person的2个子类,Man和Woman,此时Object是Man和Woman的间接父类。
3.并给Person创建一个方法method1,给Man创建一个方法method2。
二、类的实例化
首先要明白:类的实例化就是在堆(heap)内存中创建属于该类的对象,如果把对象再赋给一个变量,就相当于给这个对象起了一个名字,那么系统就会在栈(stack)中创建一个变量,并保存该对象的内存地址,如果创建时没有赋值就是所谓的匿名对象。
我们以Person的实例化为例,一旦执行
Person p = new Person()
此时堆中就是有了一个Person对象,而p中就保存了Person对象的内存地址,p所在的栈可以理解为Person类的栈,凡是Person对象的变量都存放在该栈中,而该栈中所有的变量能且只能调用Person对象的各种内部结构。
同理当实例化Man和Woman类的时候,也会发生上述过程,w和m唯一调用对应的对象。
Man m = new Man();
Woman w = new Woman();
三、重写方法
概念:子类的重写方法会覆盖父类的方法
当子类Man中重写了Person 的method1方法时,此时子类重写的方法method1会覆盖父类的method1。也就是说当m和w调用对象方法method1时,执行的是重写的方法method1。
四、调用
以p调用方法为例,方法的调用可以分两段来看:
编译阶段:栈(Person 栈)中的变量p会调用它所指向的堆(Person 堆)中的对象(Person 对象)的方法(method1);
执行阶段:变量p会将调用的方法抛给对象去执行,对象执行时也只会执行它内部有的方法,有重写就执行重写的方法。
五、多态
多态:子类对象可以赋值给父类的引用(变量),父类的引用只能调用父类的方法。
再次创建一个 Man对象,并把对象的地址赋给Person类变量pp时,那么就会在Person类的栈
中创建一个变量pp,而不是在Man的栈中创建一个变量pp,这就是多态。
Person pp = new Man();
pp.method1();
pp.method2();(报错不存在)
此时pp是在(Person栈)中,指向的是Man堆中的对象Man,但是遵循能且只能调用Person对象的各种内部结构,所以也就调用不了Man 中的结构method2。
具体过程:当pp.method1() 时,pp调用时会调用Person中的方法method1,执行时会将method1抛个Man对象,Man继承自Person,可以识别Person的方法,但执行的是Man重写的方法method1。
六、向下转型
概念:父类的引用(变量)可以强转为子类的引用(变量)
1.那pp想要调用Man中的结构,可不可以呢?
答案:可以,但需要将pp转换为Man类型的变量---因为Man是Person的子类,所以叫向下转型,通过强转符()来完成,
Man mm=(Man)pp;
mm.method2();
此时的pp被强转为了Man类型的mm,mm是在Man栈中,mm就是个纯纯的man类型,可以调用man对象的各种结构。
2.既然pp可以被向下转型,可不可以转型为woman呢?
答案:可以转换但不能执行
同理ww调用时会调用woman中的方法method1,执行时会将method1抛个Man对象,此时man对象不会执行method1,因为man和woman不发生继承关系,man对象不能识别来自平行类的方法。
Woman ww=(Woman)pp;
ww.method1();
3.再次创建一个 Man对象,并把对象的地址赋给Object 类变量oo 时,那么就会在Object类的栈
中创建一个变量oo,依然不是在Man的栈中创建一个变量oo。此时的oo和Man没有直接关系,不能调用Man中的方法。
但是oo可以转型为Person类的po,或则强转为Man的mo后也就是向下转型,就可以调用了,因为Person继承了Object,
Object oo = new Man();
oo.method1();//不能直接调用,Person不直接继承于Object
Person po=(Person)oo;//强转为Person后就可以调用了
Man mo=(Man)oo;//或强转为Man后就可以调用了
mo
po.method1();
po调用的过程同上:当po.method1() 时,po调用时会调用Person中的方法method1,执行时会将method1抛个Man对象,Man继承自Person,可以识别Person的方法,但执行的是Man重写的方法method1。
以上就是我对java继承多态的理解。