JavaSE入门---掌握面向对象三大特性:封装、继承和多态

news2024/12/27 12:49:42

文章目录

  • 封装
    • 什么是封装?
    • 如何实现封装?
  • 继承
    • 什么是继承?
    • 继承的语法
    • 父类成员访问
      • 子类访问父类的成员变量
      • 子类访问父类的成员方法
    • 认识super关键字
    • 认识final关键字
    • 子类的构造方法
      • super VS this
      • 在继承关系中各代码块的执行顺序是怎样的?
    • Java支持的继承的方式
    • 继承 VS 组合
  • 多态
    • 什么是多态?
    • 什么是重写?
      • 重写 VS 重载
    • 向上转型和向下转型
      • 向上转型
      • 向下转型

封装

什么是封装?

什么是封装呢? 简单来说就是套壳屏蔽细节

比如:对我们使用的电脑来说,在它运行过程中是有很多的部件相互配合共同执行的。但对于我们使用者而言只需要使用鼠标和键盘就可以操作电脑让它工作。 这其中就是套壳的思想,电脑把它的硬件资源全部套壳(封装起来),只留出几个接口供用户使用就可以和计算机交互。

封装的标准定义:将数据和操作数据的方法有机结合,隐藏对象的属性和实现细节,仅通过对外的公开接口来和对象进行交互。

如何实现封装?

Java中主要通过类和访问权限来实现封装。

类可以将数据和封装数据的方法结合在一起。
访问权限用来控制方法和字段能否直接在类外使用。

Java中提供了四种访问限定修饰符:来设置访问权限
在这里插入图片描述

注: default权限指:什么都不写时的默认权限。

继承

什么是继承?

Java中使用类来对现实世界中的实体进行描述,但是现实世界错综复杂,事物之间可能会存在一些关联、一些共性。比如:猫和狗,他们都是动物,因此他们就具有许多相似的属性,但又有自己独有的一些属性。比如:

在这里插入图片描述

具有这些相同属性的类还有很多,如果我们在这些类中都重新加上这些属性,代码就显的有写累赘。 因此就引入了继承。我们把所有类共同的一些属性写到一个类里,把每个类独有的部分再写到一个类中。

继承:专门用来进行共性抽取,实现代码复用。

共同的部分(类),叫作:父类、基类、超类;
独有的部分(类),叫作:子类、派生类;

继承的语法

借助extends关键字

class Animal{
    public String name;
    public int age;
    public double weight;

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

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

class Cat extends Animal{
    public void miao(){
        System.out.println("喵喵叫");
    }
}

class Dog extends Animal{
    public void bark(){
        System.out.println("汪汪叫");
    }
}

注:

  1. 子类会将父类中所有的成员变量、成员方法添加到子类中。
  2. 子类继承父类后必须新添加自己特有的成员,体现出与父类的不同,否则就没有必要继承了。

父类成员访问

子类访问父类的成员变量

  • 子类和父类中不存在同名的成员变量
class Animal{
    public String name;    //由于需要被子类对象使用,所有用public修饰
    public int age;
}

class Dog extends Animal{
    public String color;

    public void method(){
        name = "小黄";   // 直接访问父类的
        age = 2;        // 直接访问父类的
        color = "黄色";  // 访问自己的
    }
}
  • 子类和父类中存在同名的成员变量
class Animal{
    public String name;
    public int age;
}

class Dog extends Animal{
    public String name;
    public String color;

    public void method(){
        name = "小黄";   // 优先访问自己的name
        age = 2;        // 直接访问父类的
        color = "黄色";  // 访问自己的
    }
}

注:

  1. 如果访问的成员变量子类中有,优先访问自己的成员变量;
  2. 如果访问的成员变量子类中无,则访问父类继承下来的;如果父类中也没,则编译报错;
  3. 如果访问的成员变量与父类中的成员变量同名,则优先访问自己的;

子类访问父类的成员方法

  • 成员方法名字不同
class Animal{
    public void eat(){
        System.out.println("吃饭");
    }
}

class Dog extends Animal{
    public void bark(){
        System.out.println("汪汪叫");
    }

    public void method(){
        bark();    //访问子类自己的
        eat();     //访问父类的
    }
}
  • 成员方法名字相同
class Animal{
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃饭");
    }

    public void method(){
        eat();     //访问自己的
    }
}

注:

  1. 通过子类对象访问 父类与子类中不同名的方法时,优先在子类中找,找到则访问;否则在父类中找,找到则访问,否则编译报错;
  2. 通过子类对象访问 父类与子类中同名的方法时,如果父类和子类的同名方法参数列表相同,则优先访问子类自己的;如果参数列表不同,则根据调用方法时传递的参数选择合适的方法访问,若没有则报错;

认识super关键字

如果子类中存在和父类相同的成员时,如何不访问子类的成员,而去访问父类的成员呢? 这就需要用到super关键字。

super:在子类方法中访问父类的成员

class Animal{
    public String name;
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Dog extends Animal{
    public String name;
    public void eat(){
        System.out.println("狗吃饭");
    }

    public void method(){
        super.name = "动物名";   //访问父类的成员变量
        super.eat();            //访问父类的成员方法
    }
}

注:

  1. 只能在子类方法中使用;
  2. 只能在非静态方法中使用;

认识final关键字

final可以被用来修饰:变量、成员方法、类;

  • final修饰变量或字段,表示常量—不能修改;
  • final修饰类,表示此类不能被继承;
  • finnal修饰方法,表示此方法不能被重写(多态中会使用到);

子类的构造方法

父子父子,先有父再有子;即:子类对象构造时,需要先调用父类的构造方法构造父类,然后执行子类的构造方法构造子类;

class Animal{
    public Animal(){
        System.out.println("执行父类构造方法");
    }
}

class Dog extends Animal{
    public Dog(){
        System.out.println("执行子类构造方法");
    }
}

//再main中创建子类时,结果为:
//执行父类构造方法
//执行子类构造方法

为什么还会调用到父类的构造方法呢?
子类对象中成员是由两部分组成的:父类继承下来的成员和子类新增的成员;父子父子,肯定先有父再有子。因此,需要先调用父类的构造方法,将从父类继承下来的成员构造完整;再调用子类自己的构造方法,将自己新增的成员构造完整。

注:

  1. 如果父类没有定义构造方法,在子类的构造方法中第一行会隐含的调用super(),即执行父类空的构造方法。
  2. 如果父类定义了无参的构造方法,在子类的构造方法中第一行会隐含的调用super(),即执行父类无参的构造方法。
  3. 如果父类定义了有参数的构造方法,此时编译器不会默认生成隐含的super()—因为它不知道参数是啥,需要用户显示的指定父类的构造方法。
  4. 在子类构造方法中,使用super(…)调用父类的构造方法时,super必须放在子类构造方法的第一行。
  5. super只能在子类构造方法中出现一次,且不能和this同时出现。

super VS this

相同点:

  1. 都是Java的关键字;
  2. 只能在类的非静态方法中使用,访问非静态的变量和非静态的方法
  3. 在构造方法中调用时,都必须在构造方法的第一行,且不能同时存在。

不同点:

  1. this是当前对象的引用,即引用当前对象的成员;super是从父类继承下来的成员的引用,即引用父类中的成员。
  2. this是非静态成员方法的一个隐藏参数,super不是一个隐藏参数;
  3. 在构造方法中,this用来调用本类构造方法,super用来构造父类构造方法;不能同时出现在一个构造方法里。
  4. 构造方法中一定存在super的调用,用户没有写编译器也会增加;但是this用户不写则没有。

在继承关系中各代码块的执行顺序是怎样的?

class Animal{
    {
        System.out.println("父类执行实例代码块");
    }
    static {
        System.out.println("父类执行静态代码块");
    }

    public Animal(){
        System.out.println("父类执行构造方法");
    }
}

class Dog extends Animal{
    {
        System.out.println("子类执行实例代码块");
    }

    static {
        System.out.println("子类执行静态代码块");
    }

    public Dog(){
        System.out.println("子类执行构造方法");
    }
}
public class test {
    public static void main(String[] args) {
        Dog dog = new Dog();
    }
}

//结果:
父类执行静态代码块
子类执行静态代码块
父类执行实例代码块
父类执行构造方法
子类执行实例代码块
子类执行构造方法

注:

  1. 父类静态代码块优先于子类静态代码块执行,且都是最早执行;
  2. 父类实例代码块和父类构造方法再执行;
  3. 子类实例代码块和子类构造方法再执行;
  4. 实例代码块优先于构造方法执行;
  5. 第二次实例化子类对象时,父类和子类的静态代码块都不执行;

Java支持的继承的方式

在这里插入图片描述

继承 VS 组合

组合:和继承类似,也是一种表达类之间关系的方式。也能够达到代码复用的效果,它是将一个类的实例作为另一个类的字段。

//以汽车为例,说明继承和组成的不同

//轮胎类
class Tire{

}

//发动机类
class Engine{

}

//车内系统类
class VehicleSystem{

}

//组成
class Car{
    private Tire tire;
    private Engine engine;
    private VehicleSystem vehicleSystem;
}

//继承  奔驰继承了汽车类
class Benz extends Car{

}

注:

  1. 继承表示对象之间是 is-a 的关系,即 猫是动物、狗是动物;
  2. 组合表示对象之间是 has-a的关系,即 汽车有轮子、发动机、车载系统;
  3. 继承借助extends关键字,会自动将父类成员加载到子类中;组合需要手动在某个类当中引入其他类的成员;

多态

什么是多态?

多态:即多种形态;具体点就是去完成某个行为时,不同的对象去完成时会产生不同的状态。

实现多态的条件:

  1. 必须在继承体系下;
  2. 子类必须对父类方法进行重写;
  3. 通过父类的引用调用重写方法;
class Animal{
    public String name;
    public int age;
    public Animal(String name,int age){
        this.name = name;
        this.age = age;
    }

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

class Cat extends Animal{
    public Cat(String name,int age){
        super(name,age);
    }

    @Override
    public void eat() {
        System.out.println(name + "cat吃鱼");
    }
}

class Dog extends Animal{
    public Dog(String name, int age){
        super(name,age);
    }

    @Override
    public void eat() {
        System.out.println(name + "dog吃骨头");
    }
}
public class test {
    //通过父类调用eat方法才能看出来重写的作用
    //没有重写时,子类中没有eat方法,只能使用父类的eat方法,不管是哪个子类最后都会打印出 动物吃饭
    //重写后,子类中有重写的eat方法,调用父类的eat方法时,会自动识别出哪个子类调用的eat方法,会打印出对应动物的吃饭
    //
    //子类有重写方法后,当然也可以不通过调用父类eat方法,而是直接调用自己重写后的eat方法打印出对应的动物的吃饭
    //但这样就看不出重写的作用了
    public static void eat(Animal a){
        a.eat();
    }
    public static void main(String[] args) {
        Cat cat = new Cat("小猫",1);
        Dog dog = new Dog("小狗",2);
        eat(cat);
        eat(dog);
    }
}

什么是重写?

重写:也叫覆盖,是子类对父类非静态、非private修饰、非final修饰、非构造方法等的重新编写,返回值和形参都不能改变。即外壳不变,核心重写

注:

  1. 子类在重写父类方法时,一般必须与父类方法原型一致:即修饰符、返回值类型、方法名、参数列表要完全一致。
  2. 特殊情况下,返回值类型可以不同,但是必须具有父子关系。
  3. 子类中重写方法的访问权限不能比父类方法中的访问权限更低。
  4. 父类中被static修饰的、private修饰的、final修饰的方法和构造方法,不能被重写。
  5. 重写后的方法要加上 @Override 注解。

重写 VS 重载

在这里插入图片描述

向上转型和向下转型

向上转型

向上转型:实际就是创建一个子类对象,将其当成父类对象来使用。

语法格式: 父类类型 对象名 = new 子类类型()

		// animal是父类类型但是可以引用一个子类对象   把小范围的对象放到大范围的对象里
        Animal animal = new Dog("小狗",2);

使用场景:

  1. 直接赋值
  2. 方法传参
  3. 方法返回

注:

  1. 向上转型的优点:让代码实现更简单灵活。
  2. 向上转型的缺点:不能调用到子类特有的方法

向下转型

向下转型:将子类对象向上转型后就无法调用子类特有的方法,但是有时候可能需要调用到子类特有的方法,此时就需要向下转型:将父类引用再还原为子类对象

		Cat cat = new Cat("小猫",1);
        Dog dog = new Dog("小狗",2);
        
        //向上转型
        Animal animal = cat;
        
        //向下转型: 按道理可以转为继承Animal的任意子类对象  但是有些不安全
        //必须强制类型转换
        Cat cat1 = (Cat) animal;    //安全  因为向上转型时就是Cat转的
        Dog dog1 = (Dog) animal;    //不安全 会抛出异常  因为向上转型是Cat转的  但是现在却要把猫类成员赋值给狗类

Java中为了提高向下转型的安全性,引入了 instanceof :类型匹配 如果为true则可以安全转换。

		Cat cat = new Cat("小猫",1);
        Dog dog = new Dog("小狗",2);

        //向上转型
        Animal animal = cat;

        //向下转型
        if (animal instanceof Cat){
            Cat cat1 = (Cat) animal;
        }
        if (animal instanceof Dog){
            Dog dog1 = (Dog) animal;
        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1120740.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AAPCS:最新的ARM子程序调用规则

AAPCS是arm公司发布的ARM架构应用程序二进制(ABI)程序调用接口,该文档由多个版本,博主第一次ARM程序调用规则是在《ARM体系与结构编程》,但书中描述的是ATPCS,AAPCS是ATPCS的升级版。后面去ARM官网看到了AA…

冯诺依曼体结构 - 为什么要有操作系统

冯诺依曼体系结构 基础 概念认识 我们现在常见的 计算机,如 笔记本电脑,或者是不常见的 计算机,如服务器,大部分都遵循一个体系结构 -- 冯诺依曼体系结构。计算机的基本构成 就是由 冯诺依曼体系结构 来构成计算机的基本单元的。…

机械设备经营小程序商城的作用是什么

由于机械设备厂商品牌需要各地招商代理,因此在管理方面也需要工具进行高效管理。如今各个行业都在开展数字化转型解决行业所遇难题或通过线上销售解决传统三公里难题及品牌扩张难题、用户消费渠道少等难题,构建会员体系精细化管理,同时还需要…

轻松快速搭建一个本地的语音合成服务

前言 本文将介绍一个可以快速搭建本地语音合成的服务,模型和代码已全部提供,不需要联网运行。项目使用的是VITS模型结构,能够很轻松地启动服务。 安装环境 安装Pytorch。 # 安装CPU版本的Pytorch conda install pytorch torchvision torc…

【了解一下,Elastic Search的检索】

文章目录 **1.1.ES**1.1.1.elasticsearch的作用**1.1.2.ELK栈****2.索引库操作****2.1.mapping映射属性****2.2.索引库的CRUD** **3. 文档操作** **基于IDEA操作ES****索引操作****文档操作** DSL查询文档**1.1.DSL查询分类****1.2. 全文检索查询****1.3. 精准查询****1.4. 地理…

消息订阅与发布pubsub

消息订阅与发布 订阅消息:消息名发布消息:消息内容 A组件想使用C组件里面的东西,A需要数据,C是提供者。 在A组件里面订阅一个消息,假设订阅的消息名叫做Demo,指定回调函数叫test;C发布消息&…

ARM映像文件组成

引言 ARM编译器将各种源文件(汇编文件、C语言程序文件、C语言程序文件)编译生成ELF格式的目标文件(后缀为.o文件,以下将目标文件简称为.o文件),.o文件经过连接器,和C/C运行时库一起编译生成ELF格…

Kafka学习(最新版3.6.0)

文章目录 一、初识MQ1.1 什么是MQ1.2 同步和异步通讯1.1.1 同步通讯1.1.2 异步通讯 1.3 技术对比1.4 MQ的两种模式 二、初识Kafka2.1 Kafka的使用场景2.2 Kafka基本概念2.3 Topic与Partition 三、Kafka基本使用3.1 部署前的准备3.2 启动kafka服务器3.3 Kafka核心概念之Topic3.4…

Qt扫盲-QPen 理论使用总结

QPen 理论使用总结 一、概述二、Pen Style 画笔风格三、Cap Style 帽风格四、Join Style 连接处样式 一、概述 QPen 是Qt绘图控件里面的一个重要的组件,和QColor 一样也是类似的一个属性类。这个类就是描述一个画笔具有的属性。 一个画笔 Pen 有style()&#xff0…

032-第三代软件开发-Popup弹窗

第三代软件开发-Popup弹窗 文章目录 第三代软件开发-Popup弹窗项目介绍Popup弹窗官方示例项目中的代码 之前写过一个Popup抄抄别人的dimvisible 和 Open 区别 与 Dialog有啥区别其他总结一下 关键字: Qt、 Qml、 Popup、 弹窗、 modal 项目介绍 欢迎来到我们的…

外网nat+nat server,内网做路由过滤,以及ppp CHAR认证 企业网搭建

作业 网络拓扑图如下所示: 要求:做适当的截图,表示完成相应的操作。 按照网络拓扑要求搭建网络结构,按照个人学号配置每个节点的IP地址,其中X为班级号,Y为学号末尾2位;Y1为学号末尾2位1&#…

kubernetes 多集群管理和联邦集群将是下一波运维浪潮

问题 调研一下国内外K8s平台软件,哪个具有创建标准的K8s集群的功能? 背景 随着云原生技术在越来越多的企业和组织中的大规模落地,如何高效、可靠地管理大规模资源池以应对不断增长的业务挑战成为了当下云原生技术的关键挑战。在过去的很长…

第三章 内存管理 十四、页面分配策略

目录 一、驻留集 1、定义: 2、注意事项 3、分配策略 固定分配: 可变分配: 4、置换策略 局部置换: 全局置换: 5、置换分配策略 5.1、固定分配局部置换: 这种策略的缺点是: 5.2、可变分配全局置换: 5.3、可变分配局部置换: 注意: 6、何时调…

周立功ZCANPRO简介和使用

ZCANPRO目录 周立功ZCANPRO简介一、软件安装ZCANPRO官网链接:驱动官网链接 二、ZCANPRO使用1.设备管理2.选择CAN、CANFD波特率计算器使用方法(可选) 3.新建视图CAN视图DBC视图 4.发送数据普通发送DBC发送 三、高级功能UDS诊断 周立功ZCANPRO简…

分布式缓存Spring Cache

一、缓存里的数据如何和数据库的数据保持一致? 缓存数据一致性1)、双写模式2)、失效模式1、缓存数据一致性-双写模式 2、 缓存数据一致性-失效模式 我们系统的一致性解决方案: 1、缓存的所有数据都有过期时间,数据过期下一次查询触发主动更新 2、读写数据…

基于PyQt5和OpenCV库的简单的文档对齐扫描应用程序

计算机视觉-作业1 作业要求简介说明 安装运行功能使用待完善代码相关 作业要求 拍一张A4纸文稿的图片,利用角点检测、边缘检测等,再通过投影变换完成对文档的对齐扫描 简介 使用python语言,基于PyQt5和OpenCV库的简单的文档对齐扫描应用程…

教你面试就看出公司是否靠谱!

点击下方“JavaEdge”,选择“设为星标” 第一时间关注技术干货! 免责声明~ 任何文章不要过度深思! 万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案…

王道计算机考研 操作系统学习笔记 + 完整思维导图篇章五: IO管理

目录 IO设备的基本概念和分类 IO设备的分类 按使用特性分类 按传输速率分类 按信息交换单位分类 IO控制器 l/O设备的电子部件(I/O控制器) l/O控制器的组成 内存映像I/o vs.寄存器独立编址 IO控制方式 程序直接控制方式 中断驱动方式 DMA方式 ​编辑通…

Cesium添加自己的专属Logo(2023.10.22)

Cesium添加专属Logo 2023.10.22 引言1、现有网站实例展示1.1 Cesium官方Logo1.2 SuperMap官方Logo1.3 Mars3D官方Logo1.4 Xt3d个人Logo1.5 Digital Visual官方Logo1.6 AirLook官方Logo 2、两种常见的实现思路2.1 思路1(静态或动态引入Div)2.1.1 静态Div&…

Swift 判断 A B 两个时间是不是同一天,A 是不是 B 的昨天

1. 今天要做这个效果(在时间旁边显示今天,昨天) 2. Preview 3. Code: // 添加 今天 昨天 func show_today_yesterday(d: Date Date()) -> String {let calendar Calendar.currentlet today: Date Date()if calendar.isDate(today, inS…