java多态

本文详细介绍了Java中的多态性概念,包括编译类型与运行类型的区别、向上转型和向下转型的规则,以及如何通过instanceOf操作符判断对象的运行类型。通过实例展示了如何在实际编程中运用多态性,如Animal类、Cat类和Dog类的继承关系,演示了如何调用不同类的方法。
摘要由CSDN通过智能技术生成

总结:
0、编译类型与运行类型可以不一致,编译类型在定义时即确定,不能更改;运行类型可以改变,使用 getClass() 方法可以查看该引用的运行类型;
1、编译类型看左边,运行类型看右边
2、属性的值看编译类型
3、方法调用看运行类型
4、向上转型:将父类引用指向子类对象
5、向下转型:将原来指向子类对象的父类引用,转成指向子类对象的子类引用

package mypoly;

/* 多态基本介绍
    1、方法或对象具有多种形态,多态建立在封装和继承的基础之上
    2、方法多态:重载和重写就体现多态
    3、对象的多态(多态的核心):
        1)一个对象的编译类型和运行类型可以不一致
        2)编译类型在定义对象时,就确定了,不能改变
        3)运行类型可以变化
        4)编译类型看定义时 = 号的左边,运行类型看 = 的右边;
          Animal animal = new Dog();    //animal的编译类型是Animal,运行类型是Dog
          animal = new Cat();   //animal的运行类型变成了Cat, 编译类型仍然是 Animal
  多态注意事项:
    1、多态的前提是: 两个对象(类)存在继承关系
    2、多态的向上转型:
        1) 本质: 父类的引用指向了子类的对象
        2) 语法: 父类类型 引用名 = new 子类类型();
        3) 特点: 编译类型看左边,运行类型看右边
           可以调用父类中的所有成员(遵守修饰符的访问权限)
           不能调用子类中的特有成员
            - 编译阶段,根据定义的变量类型进行编译,父类中没有子类的特有成员,若调用子类中特有成员,编译时会报错
           最终运行效果看子类的具体实现
            - 运行阶段,根据对象类型来运行(调用方法),因为引用实际上是指向子类的实例化对象
            - 所以使用 引用名.方法名() 调用方法时,会先从子类开始查找
    3、多态的向下转型:
        1)语法: 子类类型 引用名 = (子类类型)父类引用;
        2)只能强转父类的引用(地址重新赋值),不能强转父类的对象
        3)要求父类的引用必须指向的是向下转型的目标类型的对象
        4)可以调用子类类型中的所有成员
    4、属性没有重写之说,属性的值看编译类型
    5、instanceOf 比较操作符,用于判断对象的 运行类型 是否为XX类型,或XX类型的子类型
*/
public class MyPoly {
    public static void main(String[] args) {
        BB bb = new BB();   // 运行类型是 BB
        System.out.println(bb instanceof BB);   // true
        System.out.println(bb instanceof AA);   // true

        AA aa = new BB();   // 运行类型是 BB
        System.out.println(aa instanceof BB);   // true
        System.out.println(aa instanceof AA);   // true

        Object obj = new Object();
        System.out.println(obj instanceof AA);  // false
        String str = "hello";
//        System.out.println(str instanceof obj);   // 编译报错
    }
}

class AA{}
class BB extends AA{}

package mypoly.polydetail;

public class Animal {

    public void eat(){
        System.out.println("吃");
    }

    public void sleep(){
        System.out.println("睡");
    }

    public void run(){
        System.out.println("跑");
    }

    public void say(){
        System.out.println("Hi~");
    }
}

//
package mypoly.polydetail;

public class Cat extends Animal{

    public void eat(){
        System.out.println("猫吃鱼");
    }

    public void cathMouse(){
        System.out.println("猫抓老鼠");
    }
}

//
package mypoly.polydetail;

public class Dog extends Cat{
}

//
package mypoly.polydetail;

public class Test {
    public static void main(String[] args) {

        // 向上转型: 父类的引用指向了子类的对象
        Animal animal = new Cat();
//        Object obj = new Cat();   //可以编译通过 Object也是Cat的父类

        // 可以调用父类中的成员(访问范围内) 但不能调用子类的特有成员
//        animal.catchMouse();  // 报错 编译阶段能调用哪些成员 由编译类型决定
        // 最终运行效果看子类中的具体实现 调用方法时 从子类的成员中开始查找调用 规则与继承一致
        animal.eat();
        animal.run();
        animal.sleep();
        animal.say();

        // 向下转型
        Cat cat = (Cat) animal;
        cat.cathMouse();
        // 要求父类的引用必须指向的是向下转型的目标类型的对象 - 即animal原来本身就是指向Cat的
        // 即使 Dog 类继承Cat类,也会运行时报错
//        Dog dog = (Dog)animal;  // 运行时报错


    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值