java面向对象三大特征之多态
多态:
同一事物有着不同的表现形式
满足的条件:
1.要有继承(子类继承父类)
2.子类对父类方法进行重写
3.要有父类引用指向子类对象。//意思就是Father f = new Son();左边是父类的引用,右边是子类的对象,new Son()在堆内存中占据空间,f指向该对象,具体内存图见下面。
多态的访问特点(附加内存图解释):
- 访问成员变量(属性值)
原则:编译看左边,访问看左边
解释: 在编译的过程中,看的是父类,运行的过程中,看的也是父类变量
举例:
public class TestVoid {
public static void main(String[] args) {
Father f = new Son(); //父类引用指向子类对象
System.out.println(f.num);
}
}
class Father{ //父类
int num =10;
}
class Son extends Father { //子类继承父类
int num =20;
}
这里创建一个父类Father,然后创建一个子类Son继承父类,最后使用父类引用f指向子类对象,调用f.sum,显示的是父类对象变量值
内存分析图:
首先类加载进入方法区,主方法进入栈内存,执行Father f,在堆内存中创建一块空间new Son(),子类对象默认通过super()调用父类的属性和方法,
f实际为Father类型,则会指向new Son中的Father属性,调用时也是调用父类属性
2.访问成员方法
原则:编译看左边,运行看右边
解释:首先这个方法被子类重写,然后父类引用调用该方法,则显示的是子类被重写的方法。即:在编译的过程中,首先查看该方法在父类中是否存在,若不存在则编译不会通过,
若在父类中存在该方法,子类也重写了该方法,则编译通过,在执行的过程会执行子类的方法—-这叫做动态绑定。真正进栈内存的是子类的print方法
public class TestVoid {
public static void main(String[] args) {
Father f = new Son(); //父类引用指向子类对象
f.fly(); //
}
}
class Father{ //父类
int num =10;
public void fly(){ //父类方法
System.out.println("father");
}
}
class Son extends Father { //子类继承父类
int num =20;
public void fly() { //子类重写父类的方法
System.out.println("son");
}
}
内存分析图:
3.访问静态成员方法
原则:编译看左边,运行看左边
解释:静态方法是属于类的,可以使用类型.方法调用,在编译和执行的过程中都看的是父类中的静态方法,
注意:静态方法是类自己的,在类型,静态方法是不能被重写的,即子类继承父类,父类中含有静态方法,子类不能对父类的静态方法进行重写,但是可以写一个一样的静态方法,
但是在多态执行的过程中,会调用各自的方法。
public class TestVoid {
public static void main(String[] args) {
Father f = new Son(); //父类引用指向子类对象
f.fly();//多态中父类引用调用静态方法
Father.fly();//父类调用静态方法
Son.fly();//子类调用静态方法
}
}
class Father{ //父类
int num =10;
public static void fly(){ //父类方法
System.out.println("father");
}
}
class Son extends Father { //子类继承父类
int num =20;
public static void fly(){
System.out.println("sss");
}
}
输出结果:
father
father
sss
如果在子类Son中不写与父类相同的静态方法,使用Son.fly(),调用的是父类的静态方法
多态的用处
多态在实际项目中的使用常作为参数传递使用
比如
public class TestVoid {
public static void main(String[] args) {
setVoice(new Dog());
setVoice(new Cat());
}
public static void setVoice (Animal a){
a.voice();
}
}
class Animal {
public void voice(){
System.out.println("动物叫");
}
}
class Dog extends Animal{
@Override
public void voice() {
System.out.println("狗叫");
}
}
class Cat extends Animal{
@Override
public void voice() {
System.out.println("猫叫");
}
}
在这个过程中,将不对子类对象传递,相当于多态的使用,然后父类引用调用子类中的方法执行