什么是多态性?
我们可以理解为一个事务的多种形态
创建一个Person类
package JavaSe;
public class Person {
public int id;
public String name;
public int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public Person(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public void setAge(int age) {
this.age = age;
}
public void eat(){
System.out.println("父类吃");
}
}
创建一个Man类继承Person类
package JavaSe;
public class Man extends Person {
public int sex;
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public Man(int id, String name, int age) {
super(id, name, age);
}
public void eat(){
System.out.println("男人吃");
}
public void sleep(){
System.out.println("男人睡");
}
}
创建一个测试类PersonTest类
public class Persontest {
public static void main(String[] args) {
//对象的多态性,父类的引用指向子类的对象
Person man = new Man(1,"leo",2);
int age = man.getAge();
man.eat();
System.out.println(age);
}
}
何为多态
对象的多态性,父类的引用指向子类的对象
Person man = new Man(1,"leo",2);
![](https://i-blog.csdnimg.cn/blog_migrate/0e301641292c7334ba1778f32b82bf93.png)
多态的使用:虚拟方法调用
有了对象的多态性以后,我们在编译期,只能调用父类种声明的方法,但在运行期,我们实际执行的是子类重写父类的方法
总结
编译看左边Person 运行看右边Man
多态性的使用前提:
类的继承
方法的重写
多态性的使用案例
package JavaSe;
import java.sql.Connection;
public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(new dog());
test.func(new cat());
}
public void func(Animal animal){
animal.eat();
animal.shout();
}
//如果没有多态性
// public void func(dog dogs){
// dogs.eat();
// dogs.shout();
// }
//
//
// public void func(cat cats){
// cats.eat();
// cats.shout();
// }
}
class Animal {
public void eat(){
System.out.println("动物:吃");
}
public void shout(){
System.out.println("动物:叫");
}
}
class dog extends Animal{
@Override
public void eat(){
System.out.println("狗吃骨头");
}
@Override
public void shout() {
System.out.println("汪,汪,汪,");
}
}
class cat extends Animal{
@Override
public void eat(){
System.out.println("猫吃鱼");
}
@Override
public void shout() {
System.out.println("喵喵喵");
}
}
class Order{
public void method(Object object){
}
}
class Driver{
public void daData(Connection connection){ //connection = new MySqlConnection()
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/294e2059c81c856c282c1f4aea465040.png)
对象的多态性,只适用于方法,不适应于属性
虚拟方法调用:
正常方法调用
Person e = new Person();
e.getInfo()
Dog dog = new Dog();
dog.eat()
虚拟方法调用(多态情况下)
子类定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父类根据赋给它不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法确定的。
Person e = new Student();
e.getInfo();//调用Student类的getInfo方法
编译时类型和运行时类型
编译时e为Person类型,而方法调用是在运行时确定的,所以调用的是Student类的getInfo()方法-----动态绑定
从编译和运行的角度看:
重载:是指运行存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名的方法就成了不同的方法。它们的调用地址在编译期就绑定了。Java重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。
所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定“或"静态绑定“
而对于多态,只有等到方法调用的那一刻,解释运行期才会确定所要调用的具体方法,这称为”晚绑定“或”动态绑定“
面试题:
多态是编译时行为还时运行时行为?
如何证明?
代码实现:
package aaaaaa;
import java.util.Random;
class Animail{
protected void eat(){
System.out.println("animal eat food");
}
}
class dog extends Animail{
protected void eat(){
System.out.println("dog eat food");
}
}
class cat extends Animail{
protected void eat(){
System.out.println("cat eat food");
}
}
class pig extends Animail{
protected void eat(){
System.out.println("pig eat food");
}
}
public class AnimalTests {
public static Animail getInstance(int key){
switch (key){
case 0:
return new cat();
case 1:
return new pig();
default:
return new dog();
}
}
public static void main(String[] args) {
int key = new Random().nextInt(3);
System.out.println(key);
Animail instance = getInstance(key);
instance.eat();
}
}
运行结果:
![](https://i-blog.csdnimg.cn/blog_migrate/15504d0ba1e4d73411f1c23273c7a7ad.png)
微信公众号:
一只Java程序猿
欢迎关注哦