java14 多态

多态

父类型引用 指向 子类型对象。

多态基础语法

关于java语言当中的多态语法机制:
Animal,Cat,Bird 三个类之间的关系
Cat 继承 Animal
Bird 继承 Animal
Cat 和 Bird 之间 没有任何继承关系

面向对象三大特征:封装 继承 多态

多态当中涉及到的概念:

向上转型(upcasting)
  子类型--->父类型
  又称为: 自动类型转换

向下转型(downcasting)
  父类型--->子类型
  又称为: 强制类型转换(需要 强制类型转换符)

两种类型之间必须存在继承关系(无论是 向上 还是 向下)

public class Animal {

  // 移动
  public void move(){
    System.out.println("动物在移动");
  }
}


// 鸟类
public class Bird extends Animal {

    // 重写从父类继承过来的方法
    public void move(){
        System.out.println("鸟在飞翔");
    }
}



// Cat
public class Cat extends Animal {

    // 重写父类继承过来的方法
    public void move(){
        System.out.println("猫在在跳");
    }

    // 不是从父类中继承过来的
    public void catchMouse(){
        System.out.println("猫抓老鼠!");
    }
}

/*
关于java语言当中的多态语法机制:
    Animal,Cat,Bird 三个类之间的关系
    Cat 继承 Animal
    Bird 继承 Animal
    Cat 和 Bird 之间 没有任何继承关系

面向对象三大特征:封装 继承 多态

多态当中涉及到的概念:

    向上转型(upcasting)
      子类型--->父类型
      又称为: 自动类型转换

    向下转型(downcasting)
      父类型--->子类型
      又称为: 强制类型转换(需要 强制类型转换符)

    两种类型之间必须存在继承关系(无论是 向上 还是 向下)

 */

public class Test {

  public static void main(String[] args) {

    // 以前写的程序
    Animal a1 = new Animal();
    a1.move();

    Cat c1 = new Cat();
    c1.move();

    Bird b1 = new Bird();
    b1.move();

    // 多态机制
    // Animal 和 Cat之间存在 继承关系,Animal是父类,Cat是子类
    // new Cat() 创建的对象的类型是Cat,a2这个引用的数据类型是Animal,可见它们进行了类型转换
    Animal a2 = new Cat(); // 子类转父类,向上转型,自动转换类型,父类型引用 指向 子类型对象


    /*
    java程序永远分为 编译阶段 和 运行阶段
    先分析 编译阶段, 再分析 运行阶段, 编译无法通过,是根本无法运行。
    编译阶段 编译器 检查a2 引用的类型 为 Animal,由于 Animal.clas
  字节码当中有move()方法,所以编译通过了,这个过程,我们称之为 静态绑定,编译阶段绑定、
  只有静态绑定成功之后,才会有后续的运行。
  在程序运行阶段,JVM内存当中 真实创建的对象是Cat对象,那么以下程序是在运行阶段
  一定会调用Cat对象的move()方法,此时发生了程序的动态绑定,运行阶段绑定、
     */
    a2.move(); // 这个时候,a2只会被当做animal类
//    多态是指,编译期 和 运行期 程序处于两个不同的状态
//    无论cat有没有重写move方法,运行阶段一定调用的是cat对象的move方法,因为底层的真是对象就是Cat对象。
//    父类型引用 指向 子类型对象 这种机制导致程序存在 编译阶段绑定 和 运行阶段绑定 两种不同的形态/状态、


//    a2.catMouse(); Animal不能使用 Cat的方法
//   以上程序不能调用 是因为 编译阶段 编译器 查到a2的类型是Animal类型
//    从Animal.class字节码文件当中 查找到catchMuouse()方法,
//    最终没有找到该方法,导致静态绑定失败,没有绑定成功,也就是说编译失败了。别谈运行了。

    // 强制类型转换:将a2从 Animal 转换为 Cat 可以让 a2这个对象 执行 catchMouse()方法
    // 向下转型,两者之间得有继承关系,必须加 强制类型转换。
    // 当调用的方法是 子类型中特有的,在父类型中不存在,必须进行 向下转型。
    Cat c2 = (Cat) a2;
    /*
    long x = 100L;
    int i = (int)x;
     */
  }
}

重写鸟类



// 鸟类
public class Bird extends Animal {

    // 重写从父类继承过来的方法
    public void move(){
        System.out.println("鸟在飞翔");
    }

    public void fly(){
        System.out.println("Bird Fly!");
    }
}

多态的向上类型转换 和 向下类型转换


/*
关于java语言当中的多态语法机制:
    Animal,Cat,Bird 三个类之间的关系
    Cat 继承 Animal
    Bird 继承 Animal
    Cat 和 Bird 之间 没有任何继承关系

面向对象三大特征:封装 继承 多态

多态当中涉及到的概念:

    向上转型(upcasting)
      子类型--->父类型
      又称为: 自动类型转换

    向下转型(downcasting)
      父类型--->子类型
      又称为: 强制类型转换(需要 强制类型转换符)

    两种类型之间必须存在继承关系(无论是 向上 还是 向下)

 */

public class Test {

  public static void main(String[] args) {

    // 以前写的程序
    Animal a1 = new Animal();
    a1.move();

    Cat c1 = new Cat();
    c1.move();

    Bird b1 = new Bird();
    b1.move();

    // 多态机制
    // Animal 和 Cat之间存在 继承关系,Animal是父类,Cat是子类
    // new Cat() 创建的对象的类型是Cat,a2这个引用的数据类型是Animal,可见它们进行了类型转换
    Animal a2 = new Cat(); // 子类转父类,向上转型,自动转换类型,父类型引用 指向 子类型对象

    /*
    java程序永远分为 编译阶段 和 运行阶段
    先分析 编译阶段, 再分析 运行阶段, 编译无法通过,是根本无法运行。
    编译阶段 编译器 检查a2 引用的类型 为 Animal,由于 Animal.clas
  字节码当中有move()方法,所以编译通过了,这个过程,我们称之为 静态绑定,编译阶段绑定、
  只有静态绑定成功之后,才会有后续的运行。
  在程序运行阶段,JVM内存当中 真实创建的对象是Cat对象,那么以下程序是在运行阶段
  一定会调用Cat对象的move()方法,此时发生了程序的动态绑定,运行阶段绑定、
     */
    a2.move(); // 这个时候,a2只会被当做animal类
//    多态是指,编译期 和 运行期 程序处于两个不同的状态
//    无论cat有没有重写move方法,运行阶段一定调用的是cat对象的move方法,因为底层的真是对象就是Cat对象。
//    父类型引用 指向 子类型对象 这种机制导致程序存在 编译阶段绑定 和 运行阶段绑定 两种不同的形态/状态、


//    a2.catMouse(); Animal不能使用 Cat的方法
//   以上程序不能调用 是因为 编译阶段 编译器 查到a2的类型是Animal类型
//    从Animal.class字节码文件当中 查找到catchMuouse()方法,
//    最终没有找到该方法,导致静态绑定失败,没有绑定成功,也就是说编译失败了。别谈运行了。

    // 强制类型转换:将a2从 Animal 转换为 Cat 可以让 a2这个对象 执行 catchMouse()方法
    // 向下转型,两者之间得有继承关系,必须加 强制类型转换。
    // 当调用的方法是 子类型中特有的,在父类型中不存在,必须进行 向下转型。
    Cat c2 = (Cat) a2;
    /*
    long x = 100L;
    int i = (int)x;
     */
    Animal a3 = new Bird(); // 父类型引用 指向 子类型对象
//    Cat c3 = (Cat) a3; //error:Bird cannot be cast to Cat
//    上面一行的程序编译没问题。因为编译器 检查到a3的数据类型是 Animal
//    Animal 和 Cat之间存在 继承关系,并且Animal是 父类型, Cat是 子类型
//    父类 转换 子类 叫做 向下转换, 语法合格。
//    程序虽然编译通过了,但是程序在运行阶段会出现异常,因为JVM堆内存当中真实存在的对象是Bird类型。
//    Bird类型的对象 无法 转换为 Cat对象,因为两种类型之间不存在任何继承关系,此时出现了著名的异常。
//    以上异常只有在强制类型转换的时候才会发生, "向下转型" 存在隐患(编译过了,但是运行错了)
//    向上转型 编译通过,运行一定不会出问题: Animal a = new Cat();
//    向下转型 编译通过,运行可能会出错: Animal a3 = new Bird(); Cat c3 = (Cat) a3;
//    如何避免向下转型,出现的classCastException异常:
//    使用instance运算符 可以避免出现以上的异常。
//      语法格式:    (引用 instanceof 数据类型名)
//      以上运算符的执行结果类型可能是布尔类型,结果可能为true,也可能为false。
//    假设(a instance of Animal):
//    true:   a 这个引用指向的对象 是一个 Animal类型
//    false:   a 这个引用指向的对象 不是一个 Animal类型


    //在进行强制类型转换之前,采用 instanceof 进行类型的判断
//    当a3的引用指向的对象确实是Cat的时候,才执行
    if (a3 instanceof Cat){ //a3 是否是 一个Cat类型的对象
      Cat c3 = (Cat) a3;
      c3.catchMouse();
    } else if (a3 instanceof Bird){ //a3 是否是 一个Bird类型的对象
      Bird b2 = (Bird) a3;
      b2.fly();
    }
  }
}

小结一下


/*
关于java语言当中的多态语法机制:
    Animal,Cat,Bird 三个类之间的关系
    Cat 继承 Animal
    Bird 继承 Animal
    Cat 和 Bird 之间 没有任何继承关系

面向对象三大特征:封装 继承 多态

多态当中涉及到的概念:

    向上转型(upcasting)
      子类型--->父类型
      又称为: 自动类型转换

    向下转型(downcasting)
      父类型--->子类型
      又称为: 强制类型转换(需要 强制类型转换符)

    两种类型之间必须存在继承关系(无论是 向上 还是 向下)

 */

public class Test {

  public static void main(String[] args) {
    // 父类型引用指向子类型对象
    // 向上转型
    Animal a1 = new Cat();
    
    Animal a2 = new Bird();
    
    // 向下转型「只有放访问子类型对象中特有的方法」
    if (a1 instanceof Cat){
      Cat c1 = (Cat) a1;
      c1.catchMouse();
    } else if (a1 instanceof Bird){
      Bird b1 = (Bird) a2;
      b1.fly();
    }
  }
}

实际应用

主人喂养宠物

主人


public class Master {

  // 主人喂养宠物
  public void feed(Cat c){
    c.eat();
  }

}



// Cat
public class Cat {
    public void eat(){
        System.out.println("小猫正在吃鱼!");
    }
}

交互


/*
  以主人喂养宠物为例子,说明多态的作用:
      主人[类]
      主人可以喂养宠物,所以主人 可以 有 喂养 动作
      宠物[类]
      宠物可以吃东西, 所以从无 可以 有 吃东西 动作

  2、面向对象编程的核心:定义好类,让类实例化为对象,给一个环境趋势一下,让各个对象之间协作形成系统。


 */
public class Test {
  public static void main(String[] args) {
    //创建主人对象
    Master zs = new Master();
    //创建猫对象
    Cat tom = new Cat();
    //主人喂养猫
    zs.feed(tom);

  }
}

低程序扩展力

增加狗对象

public class Dog{


    public void eat(){
        System.out.println("小狗正在啃骨头!");
    }
}

得修改人


public class Master {

  // 主人喂养宠物
  public void feed(Cat c){
    c.eat();
  }
  public void feed(Dog d){
    d.eat();
  }

}

测试

public class Test {
  public static void main(String[] args) {
    //创建主人对象
    Master zs = new Master();
    //创建猫对象
    Cat tom = new Cat();
    //主人喂养猫
    zs.feed(tom);

    //创建小狗
    Dog xg = new Dog();
    //主人喂养小狗
    zs.feed(xg);
  }
}

高扩展力

程序编译期,调用的是Pet方法,但是程序运行期,调用的是Cat和Dog方法。

通过多态,降低程序的耦合度,提高升序的扩展力。
能使用多态,尽量使用多态。
父类型引用指向 子类型对象。

public class Master {

  // 主人喂养宠物
  // master主人类面向的是一个抽象的Pet,不再面向具体的宠物。
  public void feed(Pet c){ //这里Pet pet 是一个父类型的引用
    c.eat();
  }
}
public class Cat extends Pet{
  public void eat(){
    System.out.println("小猫爱吃鱼!");
  }
}
public class Dog extends Pet{
    public void eat(){
        System.out.println("小狗正在啃骨头!");
    }
}


public class Snake extends Pet{
    public void eat(){
        System.out.println("蛇在吃东西!");
    }
}
public class Pet {
  // 所有的宠物都可以吃东西
  public void eat(){
  }
}


/*
  以主人喂养宠物为例子,说明多态的作用:
      主人[类]
      主人可以喂养宠物,所以主人 可以 有 喂养 动作
      宠物[类]
      宠物可以吃东西, 所以从无 可以 有 吃东西 动作

  2、面向对象编程的核心:定义好类,让类实例化为对象,给一个环境趋势一下,让各个对象之间协作形成系统。


 */
public class Test {
  public static void main(String[] args) {
    //创建主人对象
    Master zs = new Master();
    //创建猫对象
    Cat tom = new Cat();
    //主人喂养猫
    zs.feed(tom); //这个父类型的引用指向的是 子类型的变量

    //创建小狗
    Dog xg = new Dog();
    //主人喂养小狗
    zs.feed(xg); //这个父类型的引用指向的是 子类型的变量

    //创建蟒蛇
    Snake ms = new Snake();
    zs.feed(ms);
  }
}

你可能感兴趣的:(java入门,java,单例模式,java-ee)