Java多态

一、向上转型(子类引用给父类)

在之前的例子中,我们写了

Bird bird = new Bird ("圈圈");

也可以写成这样

Bird bird = new Bird ("圈圈");

Animal bird2 =  new Bird;

或者这样

Animal bird2 = new Bird("圈圈");

 

此时 bird2 是一个父类 (Animal) 的引用, 指向一个子类 (Bird) 的实例. 这种写法称为 向上转型.

向上转型发生的时机:

  • 直接赋值(上面讲的赋值就是直接赋值)
  • 方法传参
  • 方法返回

 方法传参


class Bird {
    public Bird(String name) {
        this.name = name;
    }

public class Test { 
   public static void main(String[] args) { 
       Bird bird = new Bird("圈圈"); 
       feed(bird); 
 } 
 public static void feed(Animal animal) { 
       animal.eat("谷子"); 
 } 
} 


// 执行结果
圈圈正在吃谷子

方法返回

public class Test { 
  public static void main(String[] args) { 
     Animal animal = findMyAnimal(); 
 } 
 public static Animal findMyAnimal() { 
    Bird bird = new Bird("圆圆"); 
    return bird; 
 } 
}

上述代码findMyAnimal方法返回的是一个Animal类型的引用,但是实际上却是对应到了Bird的实例

二、动态绑定(运行时绑定)       

当子类和父类中出现同名方法的时候, 再去调用会出现什么情况呢?      

接下来看下面的代码吧

                                 

//定义动物类
class Animal{
    protected String name;

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

    public void eat(String food){
        System.out.println(this.name+"animal"+food);
    }
}


class Bird extends Animal{
    public Bird(String name) {
        super(name);
    }

    @Override
    public void eat(String food) {     //子类重写eat方法
        System.out.println(this.name+"bird"+food);
    }
}

public class Test {

    public static void main(String[] args) {
        Animal animal1 = new Animal("小小");
        animal1.eat("豆子");
        Animal animal2 = new Bird("大大");
        animal2.eat("豆子");
    }
}

//打印结果
小小animal豆子
大大bird豆子

此时我们发现

  • animal1 animal2 虽然都是 Animal 类型的引用, 但是 animal1 指向 Animal 类型的实例, animal2 指向 Bird 类型的实例.
  • 针对 animal1 animal2 分别调用 eat 方法, 发现 animal1.eat() 实际调用了父类的方法, animal2.eat() 实际调用了子类的方法
因此, Java , 调用某个类的方法, 究竟执行了哪段代码 (是父类方法的代码还是子类方法的代码) , 要看究竟这个引
用指向的是父类对象还是子类对象. 这个过程是程序运行时决定的(而不是编译期), 因此称为 动态绑定

 

发生动态(运行时绑定)条件:

①继承(父类要引用子类)
②通过父类的引用调用子类和父类同名的覆盖方法

使用多态的好处是什么?
1)   类调用者对类的使用成本进一步降低.
封装是让类的调用者不需要知道类的实现细节.
多态能让类的调用者连这个类的类型是什么都不必知道, 只需要知道这个对象具有某个方法即可.
因此, 多态可以理解成是封装的更进一步, 让类调用者对类的使用成本进一步降低
2) 能够降低代码的 "圈复杂度"。
什么是圈复杂度?
  圈复杂度是描述一段代码复杂程度的方式。一段代码如果平铺直叙,那么就容易理解,而如果有很多的条件分支或者循环语句,就认为理解起来复杂
  计算一段代码中条件语句和循环语句出现的个数,这个个数就称为“圈复杂度”。若一个方法的圈复杂度太高,就需要考虑重构
3) 可扩展能力更强.
### Java 多态的概念 Java 中的多态是指同一个接口或类可以有多种不同的实现方式。它允许程序在运行时决定调用哪个方法,从而提高代码的灵活性和可扩展性。多态的核心机制依赖于继承、重写以及动态绑定。 #### 动态绑定 当子类覆盖父类的方法时,在运行期间会根据对象的实际类型来决定执行哪一个版本的方法[^1]。这是多态的关键特性之一。 ### 实现多态的方式 Java多态可以通过以下两种主要形式实现: 1. **方法重写(Override)** 2. **接口实现** 以下是具体示例说明如何利用 `instanceof` 运算符避免潜在异常并展示多态的应用场景。 --- ### 示例代码:Java 多态的具体应用 下面是一个完整的例子,展示了如何通过多态性和 `instanceof` 来处理不同类型的对象实例。 ```java // 定义一个基类 Animal class Animal { void makeSound() { System.out.println("Some generic sound"); } } // 子类 Dog 继承自 Animal 并重写了 makeSound 方法 class Dog extends Animal { @Override void makeSound() { System.out.println("Bark"); } // 额外的功能只属于狗 void fetchStick() { System.out.println("Fetching stick..."); } } // 子类 Cat 继承自 Animal 并重写了 makeSound 方法 class Cat extends Animal { @Override void makeSound() { System.out.println("Meow"); } // 额外的功能只属于猫 void climbTree() { System.out.println("Climbing tree..."); } } public class PolymorphismExample { public static void main(String[] args) { // 创建多个动物对象并通过向上转型存储它们 Animal myDog = new Dog(); Animal myCat = new Cat(); // 调用各自的 makeSound 方法 myDog.makeSound(); // 输出 Bark myCat.makeSound(); // 输出 Meow // 如果需要访问特定子类功能,则需使用 instanceof 和强制转换 if (myDog instanceof Dog) { ((Dog) myDog).fetchStick(); // 正确调用了 Dog 类中的特有方法 } if (myCat instanceof Cat) { ((Cat) myCat).climbTree(); // 正确调用了 Cat 类中的特有方法 } Object cValue = 42; // 假设我们有一个未知类型的变量 // 判断其实际类型并打印相应消息 System.out.println("The type of value is " + (cValue instanceof Double ? "Double" : (cValue instanceof Integer ? "Integer" : "Unknown"))); // 输出 Integer [^2] } } ``` 上述代码片段中: - 我们定义了一个通用的 `Animal` 类作为超类。 - 然后创建两个派生类 `Dog` 和 `Cat`,分别实现了自己的行为逻辑。 - 在主函数里演示了即使将这些对象赋给更广泛的父类引用 (`Animal`),仍然能够正确表现出各自的行为特征——这就是所谓的“编译看声明类型, 执行找真实类型”。 另外还加入了关于 `instanceof` 关键字使用的部分,用于确认某个对象的确切类别以便安全地进行向下造型操作而不会引发 ClassCastException 错误。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值