Java 之 多态

发布于:2025-08-10 ⋅ 阅读:(16) ⋅ 点赞:(0)

一、多态

  • 多态故名思义,多种状态。比如Animal 这个类中,eat 方法是 公共的方法,但是当 People,Dog , Cat,继承时,我们知道人要吃的是米饭,狗要吃的是狗粮,猫要吃的是猫粮。所以当不同类型的引用(不同的对象)调用同一方法时,虽然是同一方法,但是产生的效果却是不一样的,这就叫多态

1.1、多态的概念

  • 当不同的引用(不同的对象)调用同一方法时,产生不同的结果

1.2、多态的实现条件(缺一不可)

  • 需要在继承的前提下
  • 子类需要对父类的方法进行重写
  • 需要父类的引用调用重写方法

1.3、多态的好处

  • 比如说以前的手机来电,他只能显示电话号码。现在的手机不仅可以显示电话号码,还显示名字,地址。这样的改变,如果我有多态,就不需要对以前的代码进行修改,我只需要重新创建一个类,继承以前的那个类,重写一下来电显示那个方法就行
  • 这样使得代码的可扩展性更强了

二、重写

  • 在重写代码的前一行,加上@Override,可以让编译器帮我们效验我们重写得对不对
  • 重写和重载都是多态的表现

2.1、什么是重写?

  • 重写是对父类的方法,在子类中重新写
  • 在子类中的方法,访问权限要大于等于父类的,类型要完全相同,方法名要完全一样,参数列表也要完全一样

2.2、重写的规则

  • 子类中的重写方法的访问权限要大于等于父类中的
  • 父类中需要重写的方法不能用 static, private ,final修饰,否则不能重写,构造方法也不能重写
  • 子类中的重写方法的返回值类型可以和父类的不一样,但是这个返回值类型必须和父类构成继承关系,这个叫协变类型

2.3、重写和重载的区别

  • 访问权限:重写:要求必须大于或等于父类的访问权限,重载:要求要相同
  • 返回值类型:重写:要求要完全一致,重载:不要求
  • 方法名:重写:要求完全一致,重载:也是要求完全一致
  • 参数列表:重写:要求完全一致,重载:参数列表必须不同(类型,名字,顺序)

2.4、动态绑定

  • 比如说我用 Animal 类,实例化一个Dog 对象(向上转型),我们知道,animal这个引用虽然指的是Dog,但是animal 的类型是Animal,所以animal这个引用只能调用Animal中的成员,不能调用Dog中特有的成员。换句话说,父类的引用只能调用父类中的成员,不能调用子类的成员。更深层的意思就是,发生了向上转型不能调用制类特色的成员
  • 什么是动态绑定?动态绑定也叫做运行时绑定。当我用animal调用重写的方法时,本应该调用的是父类中的方法,但是实际是调用了子类中的重写方法。这就是动态绑定
class Animal {
  public void eat(){
   sout("父类"+"正在吃饭...")
  }
}
class Dog extends Animal{
@Override
 public void eat(){           //重写父类方法
 sout("子类"+"正在吃饭...")
 }
}
class Tect{
  Animal animal = new Dog();  //向上转型
  //此时调用的eat本应调用的是父类的eat,但实际是调用了子类Dog中的eat,
     因为此时发生了动态绑定
  animal.eat;                    //父类引用调用重写方法
                                  
                                 //所以说发生了多态
}
  • 同一个引用调用同一个方法,当这个引用 ,引用的对象不一样的时候,调用方法产生的结果也不一样,此时我们就把这种思想称之为多态

2.5、静态绑定

  • 什么是静态绑定?静态绑定也叫做(就是在写代码时绑定)编译时绑定。例子就是重载,跟据所传入的参数来调用合适的方法,此时就发生了静态绑定。(因为方法名字一样,所以根据你传入的参数来绑定要调用的方法,这就叫编译时绑定)

三、向上转型和向下转型

3.1、什么是向上转型,什么是向下转型?

  • 向上转型就是父类引用指向子类对象
Animal animal = new Dog();
  • 向下转型就是子类引用指向父类对象
Dog dog = (Dog)new Animal();

3.1.2、在向上转型中两个类型不一样,为什么不需要强制类型转换?

  • 可以这么说,狗一定是动物,但动物不一定是狗,所以向下转型需要强转

3.2、使用场景

  • 直接赋值
Animal animal = new Dog();
  • 作为参数传递
public static void get(Animal animal){     //把dog传过来就发生了向上转型
 animal.draw();
}
Dog dog = new Dog();
get(dog);
  • 作为返回值传递
public Animal get(){             //返回值应该是Animal类型
  return new Dog();           //但返回值是Dog实例化出来的对象,发生了向上转型
} 

3.3、需要注意什么?

  • 向上转型和向下转型,其实都是为了类型的统一
  • 向下转型需要注意,因为动物不一定是狗。所以可以使用 instanceof 关键字来让编译器效验是不是强转的类型,即用该关键字验证animal 所指的对象是不是狗,这样使用instanceof 保证了向下转型的安全性
Animal animal = new Dog();
if(animal instanceof Dog){
  Dog dog1 = (Dog) animal;
}else if(animal instanceof Cat){
  Cat cat = (Cat) animal;
}

四、避免在构造方法中调用重写方法

  • 因为极易出现很难找出的隐藏问题

网站公告

今日签到

点亮在社区的每一天
去签到