java特征:多态性

这篇具有很好参考价值的文章主要介绍了java特征:多态性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

多态的形式和体现

对象的多态性

多态性,是面向对象中最重要的概念,在Java中的体现:对象的多态性:父类的引用指向子类的对象

格式:(父类类型:指子类继承的父类类型,或者实现的接口类型)

父类类型 变量名 = 子类对象;

举例:

Person p = new Student();

Object o = new Person();//Object类型的变量o,指向Person类型的对象

o = new Student(); //Object类型的变量o,指向Student类型的对象

对象的多态:在Java中,子类的对象可以替代父类的对象使用。所以,一个引用类型变量可能指向(引用)多种不同类型的对象

多态的理解

Java引用变量有两个类型:编译时类型运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。

  • 若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
  • 多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法)
    “看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)

多态的使用前提:① 类的继承关系 ② 方法的重写

举例

public class Pet {
    private String nickname; //昵称

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public void eat(){
        System.out.println(nickname + "吃东西");
    }
}
public class Cat extends Pet {
    //子类重写父类的方法
    @Override
    public void eat() {
        System.out.println("猫咪" + getNickname() + "吃鱼仔");
    }

    //子类扩展的方法
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}
public class Dog extends Pet {
    //子类重写父类的方法
    @Override
    public void eat() {
        System.out.println("狗子" + getNickname() + "啃骨头");
    }

    //子类扩展的方法
    public void watchHouse() {
        System.out.println("看家");
    }
}
1、方法内局部变量的赋值体现多态

public class TestPet {
    public static void main(String[] args) {
        //多态引用
        Pet pet = new Dog();
        pet.setNickname("小白");

        //多态的表现形式
        /*
        编译时看父类:只能调用父类声明的方法,不能调用子类扩展的方法;
        运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法体;
         */
        pet.eat();//运行时执行子类Dog重写的方法
//      pet.watchHouse();//不能调用Dog子类扩展的方法

        pet = new Cat();
        pet.setNickname("雪球");
        pet.eat();//运行时执行子类Cat重写的方法
    }
}
2、方法的形参声明体现多态
public class Person{
    private Pet pet;
    public void adopt(Pet pet) {//形参是父类类型,实参是子类对象
        this.pet = pet;
    }
    public void feed(){
        pet.eat();//pet实际引用的对象类型不同,执行的eat方法也不同
    }
}
public class TestPerson {
    public static void main(String[] args) {
        Person person = new Person();

        Dog dog = new Dog();
        dog.setNickname("小白");
        person.adopt(dog);//实参是dog子类对象,形参是父类Pet类型
        person.feed();

        Cat cat = new Cat();
        cat.setNickname("雪球");
        person.adopt(cat);//实参是cat子类对象,形参是父类Pet类型
        person.feed();
    }
}
3、方法返回值类型体现多态
public class PetShop {
    //返回值类型是父类类型,实际返回的是子类对象
    public Pet sale(String type){
        switch (type){
            case "Dog":
                return new Dog();
            case "Cat":
                return new Cat();
        }
        return null;
    }
}
public class TestPetShop {
    public static void main(String[] args) {
        PetShop shop = new PetShop();

        Pet dog = shop.sale("Dog");
        dog.setNickname("小白");
        dog.eat();

        Pet cat = shop.sale("Cat");
        cat.setNickname("雪球");
        cat.eat();
    }
}

成员变量没有多态性

  • 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。

  • 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量

/**
 * ClassName: dsad
 * Package: PACKAGE_NAME
 * Description:
 *
 * @Author Thmiao
 * @Create 2023/7/5 03:02
 * @Version 1.0
 */
public class TestVariable {
    public static void main(String[] args) {
        Base b = new Sub();
        System.out.println(b.a);//1
        System.out.println(((Sub)b).a);//2

        Sub s = new Sub();
        System.out.println(s.a);//2
        System.out.println(((Base)s).a);//1
    }
}
class Base{
    int a = 1;
}
class Sub extends Base{
    int a = 2;
}

向上转型与向下转型

首先,一个对象在new的时候创建是哪个类型的对象,它从头至尾都不会变。即这个对象的运行时类型,本质的类型用于不会变。但是,把这个对象赋值给不同类型的变量时,这些变量的编译时类型却不同。

为什么要类型转换

因为多态,就一定会有把子类对象赋值给父类变量的时候,这个时候,在编译期间,就会出现类型转换的现象。

但是,使用父类变量接收了子类对象之后,我们就不能调用子类拥有,而父类没有的方法了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做类型转换,使得编译通过

java特征:多态性,Java,java,python,开发语言
向上转型:当左边的变量的类型(父类) > 右边对象/变量的类型(子类),我们就称为向上转型

  • 此时,编译时按照左边变量的类型处理,就只能调用父类中有的变量和方法,不能调用子类特有的变量和方法了
  • 但是,运行时,仍然是对象本身的类型,所以执行的方法是子类重写的方法体。
  • 此时,一定是安全的,而且也是自动完成的

向下转型:当左边的变量的类型(子类)<右边对象/变量的编译时类型(父类),我们就称为向下转型

  • 此时,编译时按照左边变量的类型处理,就可以调用子类特有的变量和方法了
  • 但是,运行时,仍然是对象本身的类型
  • 不是所有通过编译的向下转型都是正确的,可能会发生ClassCastException,为了安全,可以通过isInstanceof关键字进行判断
如何向上或向下转型

向上转型:自动完成

向下转型:(子类类型)父类变量

public class ClassCastTest {
    public static void main(String[] args) {
        //没有类型转换
        Dog dog = new Dog();//dog的编译时类型和运行时类型都是Dog

        //向上转型
        Pet pet = new Dog();//pet的编译时类型是Pet,运行时类型是Dog
        pet.setNickname("小白");
        pet.eat();//可以调用父类Pet有声明的方法eat,但执行的是子类重写的eat方法体
//        pet.watchHouse();//不能调用父类没有的方法watchHouse

        Dog d = (Dog) pet;
        System.out.println("d.nickname = " + d.getNickname());
        d.eat();//可以调用eat方法
        d.watchHouse();//可以调用子类扩展的方法watchHouse

        Cat c = (Cat) pet;//编译通过,因为从语法检查来说,pet的编译时类型是Pet,Cat是Pet的子类,所以向下转型语法正确
        //这句代码运行报错ClassCastException,因为pet变量的运行时类型是Dog,Dog和Cat之间是没有继承关系的
    }
}
instanceof关键字

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验。如下代码格式:

//检验对象a是否是数据类型A的对象,返回值为boolean型
对象a instanceof 数据类型A 
  • 说明:
    • 只要用instanceof判断返回true的,那么强转为该类型就一定是安全的,不会报ClassCastException异常。
    • 如果对象a属于类A的子类B,a instanceof A值也为true。
    • 要求对象a所属的类与类A必须是子类和父类的关系,否则编译错误。

代码:文章来源地址https://www.toymoban.com/news/detail-523436.html

public class TestInstanceof {
    public static void main(String[] args) {
        Pet[] pets = new Pet[2];
        pets[0] = new Dog();//多态引用
        pets[0].setNickname("小白");
        pets[1] = new Cat();//多态引用
        pets[1].setNickname("雪球");

        for (int i = 0; i < pets.length; i++) {
            pets[i].eat();

            if(pets[i] instanceof Dog){
                Dog dog = (Dog) pets[i];
                dog.watchHouse();
            }else if(pets[i] instanceof Cat){
                Cat cat = (Cat) pets[i];
                cat.catchMouse();
            }
        }
    }
}

到了这里,关于java特征:多态性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【Java基础教程】(十四)面向对象篇 · 第八讲:多态性详解——向上及向下转型、关键字 final与 instanceof的作用~

    【Java基础教程】(十四)面向对象篇 · 第八讲:多态性详解——向上及向下转型、关键字 final与 instanceof的作用~

    掌握final 的主要作用及使用; 掌握对象多态性的概念以及对象转型的操作; 掌握instanceof 的主要作用及使用; 在Java 中 final称为终结器,在Java 里面可以使用 final定义类、方法和属性,用于表示不可变性 。 final 类:当一个类被声明为 final 时,意味着该类不能被

    2024年02月16日
    浏览(45)
  • 实训7:虚函数与多态性

    参考代码 by 小喾苦 答案仅供参考! 实验目的 掌握运算符重载的方法; 实验任务 参考实验指导书第八章的实验任务 1。 实验步骤 参考实验指导书第八章的实验步骤 1。 测试说明 平台会对你编写的代码进行测试: 输入描述:空格隔开的两个整数x和y,表示一个坐标 输出描述

    2024年02月07日
    浏览(22)
  • C# 类class、继承、多态性、运算符重载,相关练习题

    34.函数重载 35.几个相同的函数  print() ,用于打印不同的数据类型。   36.基类和派生类   37.基类的初始化   38.多重继承   39.动态多态性   40.抽象性和虚方法   41.通过虚方法 area() 来计算不同形状图像的面积   42.运算符重载的实现   @www.runoob.com 

    2024年02月09日
    浏览(14)
  • 【C++入门到精通】C++入门 —— 继承(基类、派生类和多态性)

    【C++入门到精通】C++入门 —— 继承(基类、派生类和多态性)

    前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的命名空间的一些知识点以及关于C++的缺省参数、函数重载,引用 和 内联函数也认识了什么是类和对象以及怎么去new一个 ‘对象’ ,也了解了C++中的模版,以及学习了几个STL的结构也相信大家都掌握

    2024年02月11日
    浏览(11)
  • 【期末不挂科-C++考前速过系列P5】大二C++实验作业-多态性(3道代码题)【解析,注释】

    【期末不挂科-C++考前速过系列P5】大二C++实验作业-多态性(3道代码题)【解析,注释】

    前言 大家好吖,欢迎来到 YY 滴C++考前速过系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《

    2024年01月25日
    浏览(62)
  • Java三大特征之多态

    Java三大特征之多态

    多态的概念:通俗来说,就是 多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状态。 总的来说:同一件事情,发生在不同对象身上,就会产生不同的结果。 在java中要实现多态,必须要满足如下几个条件,缺一不可: 1. 必须在继承体系下 2.

    2024年02月13日
    浏览(11)
  • 图书管理借阅系统【Java简易版】Java三大特征封装,继承,多态的综合运用

    图书管理借阅系统【Java简易版】Java三大特征封装,继承,多态的综合运用

    前言 前几篇文章讲到了Java的基本语法规则,今天我们就用前面学到的数组,类和对象,封装,继承,多态,抽象类,接口等做一个图书管理借阅系统。 Java语言是面向对象的,所以首先要分析完成这个图书管理系统,有哪些对象: 👱使用者User 📘书Book 📲操作Operation 使用者

    2024年02月14日
    浏览(13)
  • 【Java SE语法篇】8.面向对象三大特征——封装、继承和多态

    【Java SE语法篇】8.面向对象三大特征——封装、继承和多态

    📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 面向对象三大特性:封装、继承和多态。 在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部

    2024年02月01日
    浏览(19)
  • c、c++、java、python、js对比【面向对象、过程;解释、编译语言;封装、继承、多态】

    c、c++、java、python、js对比【面向对象、过程;解释、编译语言;封装、继承、多态】

    目录 内存管理、适用 区别 C 手动内存管理:C语言没有内置的安全检查机制,容易出现内存泄漏、缓冲区溢出等安全问题。 适用于系统级编程 C++ 手动内存管理:C++需要程序员手动管理内存,包括分配和释放内存,这可能导致内存泄漏和指针错误。 适用于游戏引擎和系统级编

    2024年02月08日
    浏览(15)
  • 年度语言之--c#与java的多态

    年度语言之--c#与java的多态

    引言 多态是面向对象编程中的一个核心概念,它赋予语言更强大的表达力和灵活性。 Java和C#作为广泛使用的两中面向对象编程语言,多态这一特性都起到重要的作用,但它们实现这一概念的方式存在着一些差异。 本文将讨论Java与C#在实现多态方面的不同。 我们将分析这两种

    2024年02月22日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包