java多态 深入浅出

时间:2022-10-21 16:20:27

最近培训的堂弟昨晚问了我一个问题,说多态是什么,

我感觉是:一个类中,有几个方法,他们的方法名都是method,只不过他们的参数个数、类型或者返回值不同。

然后他说:我们老师说:子类、父类之间,向上转型*&……%¥#2@4¥5%6,它只能访问自己定义的方法,&……%#@¥%……&,

我感觉我有点迷糊,自己网上搜了下,发现java中讲的多态还有另外一种定义:

多态存在的三个必要条件

一、要有继承;

二、要有重写;

三、父类引用指向子类对象。

实现多态的技术称为

动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。


堂弟啊,估计你是听不懂上面这几句话,因为我觉得我刚毕业时,可能也无法理解,来个通俗一点的,我们顺便解释下重写和重载的区别,

1、方法的重写和重载是Java多态性的不同表现。 多态有两种表现,我开始说的方法名相同,参数不同,就是重载的意思。

2、重写是父类与子类之间多态性的一种表现。 重写:必须有继承的存在啊,

3、重载是一个类中多态性的一种表现。 看到我标红的没?一个类中:同名的方法,不同的参数个数,类型,返回值类型。

4、如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写。 重写必须是子类和父类的方法:他们名称相同、参数相同、返回类型相同,否则就是重载了。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。 

5、如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载。重载的方法是可以改变返回值的类型的。 

能懂吗?

不懂的话,我再解释一下:对于java来说,父类引用指向子类对象,这个引用是一个指针,这个引用存放在栈中,具体来说是:存放在虚拟机栈中的局部变量表的......,它存的是实际对象在堆中的地址(),这个对象实际存放在java堆中,刚创建时,这个对象放在eden空间,一次gc之后,它可能会到Survivor或者老年代中,。。。。。好吧,我也不懂自己说什么了,看例子来讲。


父类:Animal

package Java_duotai;

public class Animal {

String name;
int age;

public Animal(String name, int age){
this.name = name;
this.age = age;
}

public Animal(){

}

public void showInfo(){
System.out.println("父类Animal说:我是周杰伦");
}

public void showAnimal(){
System.out.println("我是Animal");
}

}

子类:Cat

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

package Java_duotai;

public class Cat extends Animal{

String food; //Cat定义了自己的属性

public Cat(String food){ //Cat定义了自己的有参数构造方法
this.food = food;
}

//重写了父类的showInfo()方法,
@Override
public void showInfo(){
System.out.println("子类Cat说:我是昆凌!我花杰伦钱,但我不是马蓉");
}

//定义了自己特有的showInfoCat()方法,
public void showInfoCat(){
System.out.println("子类Cat自己定义的方法");
}

}

测试方法:

package Java_duotai;
/**
* 指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。
* 若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。
*
*/

public class test_test {

public static void main(String[] args){

Animal a = new Cat("老鼠"); //向上转型 父类Animal的引用指向了自己的子类Cat的对象

a.showAnimal(); //a可以访问Animal自己类中定义的方法showAnimal

a.showInfo(); //a应该是访问Animal自己类中定义的方法showInfo,但是由于子类Cat重写了showInfo,所以这里面调用的是子类Cat的showInfo方法

//a.showInfoCat(); //这句话直接报错,因为a是父类Animal的引用,它只能调用Animal自己的方法,或者Cat中重写了其父类Animal的方法showInfo

Cat cat = (Cat) a; //向下转型,这个时候,cat这个引用,可以访问Cat类中的所有方法了,因为它就是一个Cat对象了。
cat.showInfo();
cat.showInfoCat();
cat.showAnimal(); //子类也可以直接调用父类的方法(前提是父类的showAnimal方法是public的,否则不能调用)
}
}

运行结果:

run:
我是Animal
子类Cat说:我是昆凌!我花杰伦钱,但我不是马蓉
子类Cat说:我是昆凌!我花杰伦钱,但我不是马蓉
子类Cat自己定义的方法
我是Animal
成功构建 (总时间: 0 秒)

对着运行结果,看上面的程序,希望你能懂。