Java系列——封装、继承、多态初了解

2023-10-26

目录

一、前言

二、封装

1.什么是封装?  

2.封装的特点

3.封装的使用

三、继承

1.什么是继承?

2.继承的特点

3.继承的优点

4.继承的使用 

4.1 继承的格式

 4.2 继承的演示

4.3 成员变量

4.4 成员方法

4.5 构造方法

五、多态

1.什么是多态?

2.多态的特点

3.多态的使用 

4.引用类型转型

 5.为什么要做转型?

 六、总结


一、前言

         今天总结一下关于Java的三大特性,封装,继承,多态。其实关于三大特性对于从事编程人员来说都是基本的了,毕竟只要接触Java这些都是先要认识的,接下来就系统总结一下。

二、封装

1.什么是封装?  

        封装(Encapsulation)是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。

  • 将类的某些信息隐藏在类的内部,不允许外部程序进行直接的访问调用。
  • 通过该类提供的方法来实现对隐藏信息的操作和访问。
  • 隐藏对象的信息。
  • 留出访问的对外接口。

​ 举个比较通俗的例子,比如我们的USB接口。如果我们需要外设且只需要将设备接入USB接口中,而内部是如何工作的,对于使用者来说并不重要。而USB接口就是对外提供的访问接口。

2.封装的特点

  • 对成员变量实行更准确的控制。
  • 封装可以隐藏内部程序实现的细节。
  • 良好的封装能够减少代码之间的耦合度。
  • 外部成员无法修改已封装好的程序代码。
  • 方便数据检查,有利于保护对象信息的完整性,同时也提高程序的安全性。
  • 便于修改,体高代码的可维护性。

3.封装的使用

        使用 private 关键字来修饰成员变量。对需要访问的成员变量,提供对应的一对 getXxx 方法 、 setXxx 方法。private是一个权限修饰符,代表最小权限, 可以修饰成员变量和成员方法, 被private修饰后的成员变量和成员方法,只在本类中才能访问。代码示例:


public class Student {
  private String name;
  private int age;
 public void setName(String name) {
    this.name = name;
  } 
 public String getName() {
    return name;
  }
 public void setAge(int age) {
    this.age = age;
  } 
 public int getAge() {
    return age;
  }
}

分析:对于上面的一个实体对象,我想大家都已经很熟悉了。将对象中的成员变量进行私有化,外部程序是无法访问的。但是我们对外提供了访问的方式,就是set和get方法。而对于这样一个实体对象,外部程序只有赋值和获取值的权限,是无法对内部进行修改,因此我们还可以在内部进行一些逻辑上的判断等,来完成我们业务上的需要。

三、继承

1.什么是继承?

​        继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。当然,如果在父类中拥有私有属性(private修饰),则子类是不能被继承的。

2.继承的特点

2.1 只支持单继承,一个子类只允许有一个父类

2.2 子类可以拥有父类的属性和方法

2.3 子类可以拥有自己的属性和方法

2.4 子类可以重写父类的方法

2.5 可以声明父类,创建子类(又称作为父类装载子类)

      例如:Person p=new Teacher();

                (1) 声明什么样的类型,就只能调用什么类型的属性和方法

                (2) 创建什么样的类型,就真正运行的什么类型的方法

                 提示: (1)和(2)称为向上转型, 例如:Person p=new Teacher();那么p只能调用Person类中的方法和属性,但实际上运行的是Teacher中所重写的方法,无法调用Teacher中的私有的方法

                (3) 创建什么样的类型,就可以强转为什么类型

                 提示:例如: Person p=new Teacher();

                                       Teacher t=(Teacher) p;

                 这种叫做向下转型,此时t调用的是创建的Teacher类型的相应属性和方法。

3.继承的优点

  • 提高代码发复用性
  • 父类的属性方法可以用于子类
  • 可以轻松定义子类
  • 使设计应用程序变得简单

4.继承的使用 

4.1 继承的格式

class 父类 {
  ...
} 
 
class 子类 extends 父类 {
...
}

 4.2 继承的演示

/
* *
 定义员工类Employee,做为父类
*/
 
class Employee {
    String name; // 定义name属性
   // 定义员工的工作方法
   public void work() {
 System.out.println("尽心尽力地工作");
}
} 
 
/
* *
定义讲师类Teacher 继承 员工类Employee
*/
class Teacher extends Employee {
// 定义一个打印name的方法
public void printName() {
System.out.println("name=" + name);
  }
}
 
 /
* *
定义测试类
*/
 
public class ExtendDemo01 {
public static void main(String[] args) {
// 创建一个讲师类对象
Teacher t = new Teacher();
// 为该员工类的name属性进行赋值
t.name = "小明";
// 调用该员工的printName()方法
t.printName(); // name = 小明
// 调用Teacher类继承来的work()方法
t.work(); // 尽心尽力地工作
 }
}

4.3 成员变量

        当成员变量不重名时,对代码的访问是没有影响的,但是当成员的变量重名时,这个时候访问就会出现问题,例如:


class Fu {
// Fu中的成员变量。
int num = 5;
} 
 
class Zi extends Fu {
// Zi中的成员变量
int num = 6;
public void show() {
// 访问父类中的num
System.out.println("Fu num=" + num);
// 访问子类中的num
System.out.println("Zi num=" + num);
}
} 
 
class ExtendsDemo03 {
public static void main(String[] args) {
// 创建子类对象
Zi z = new Zi();
// 调用子类中的show方法
z.show();
}
} 
 
演示结果:
Fu num = 6
Zi num = 6

        子父类中出现同名的成员变量时,在子类中访问父类中的非私有成员变量时,需要使用super关键字来修饰父类成员变量,类似于this。例如:

class Zi extends Fu {
// Zi中的成员变量
int num = 6;
public void show() {
//访问父类中的num
System.out.println("Fu num=" + super.num);
//访问子类中的num
System.out.println("Zi num=" + this.num);
}
} 
 
演示结果:
Fu num = 5
Zi num = 6

4.4 成员方法

        当成员方法出现重名时,我们则需要用到方法重写(Override)。

        方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。

class Phone {
public void sendMessage(){
System.out.println("发短信");
} 
 
public void call(){
System.out.println("打电话");
}
 
public void showNum(){
System.out.println("来电显示号码");
 }
}
//智能手机类
class NewPhone extends Phone {
//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
public void showNum(){
//调用父类已经存在的功能使用super
super.showNum();
//增加自己特有显示姓名和图片功能
System.out.println("显示来电姓名");
System.out.println("显示头像");
}
} 
public class ExtendsDemo06 {
public static void main(String[] args) {
// 创建子类对象
NewPhone np = new NewPhone();
// 调用父类继承而来的方法
np.call();
// 调用子类重写的方法
np.showNum();
}
}

注意:这里在重写时,用到了super.父类成员方法,表示调用父类成员的方法。

4.5 构造方法

        首先我们要回忆两个事情,构造方法的定义格式和作用。
        1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
        2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

class Fu {
 private int n;
 Fu(){
  System.out.println("Fu()");
  }
}
 
class Zi extends Fu {
  Zi(){
 // super(),调用父类构造方法
  super();
  System.out.println("Zi()");
  }
} 
public class ExtendsDemo07{
  public static void main (String args[]){
  Zi zi = new Zi();
  }
}
 
输出结果:
Fu()
Zi()

五、多态

1.什么是多态?

        多态是同一个行为具有多个不同表现形式或形态的能力。

2.多态的特点

  1. 消除类型之间的耦合关系,实现低耦合
  2. 灵活性
  3. 可扩充性
  4. 可替换性

3.多态的使用 

多态体现的格式:

父类类型 变量名 = new 子类对象;
变量名.方法名();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。

定义父类:

public abstract class Animal {
    public abstract void eat();
}

定义子类:

class Cat extends Animal {
    public void eat() {
        System.out.println("吃鱼");
    }
} 
 
class Dog extends Animal {
    public void eat() {
        System.out.println("吃骨头");
    }
}

定义测试类:


public class Test {
    public static void main(String[] args) {
        // 多态形式,创建对象
        Cat c = new Cat();
        Dog d = new Dog();
        // 调用showCatEat
        showCatEat(c);
        // 调用showDogEat
        showDogEat(d);
        /*
        以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代
        而执行效果一致
        */
        showAnimalEat(c);
        showAnimalEat(d);
    }
    public static void showCatEat (Cat c){
        c.eat();
    } 
    public static void showDogEat (Dog d){
        d.eat();
    } 
    public static void showAnimalEat (Animal a){
        a.eat();
    }
}

        由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当然可以把Cat对象和Dog对象,传递给方法。
        当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致,所以showAnimalEat完全可以替代以上两方法。
        不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用showAnimalEat都可以完成。
        所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。

4.引用类型转型

多态的转型分为向上转型与向下转型两种:
向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。
使用格式

父类类型 变量名 = new 子类类型();
如:Animal a = new Cat();

向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
使用格式:

子类类型 变量名 = (子类类型) 父类变量名;
如:Cat c =(Cat) a;

 5.为什么要做转型?

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

定义类:

abstract class Animal {
    abstract void eat();
} 
 
class Cat extends Animal {
    public void eat() {
        System.out.println("吃鱼"); 
    } 
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
} 
class Dog extends Animal {
    public void eat() {
        System.out.println("吃骨头");
    }
    public void watchHouse() {
        System.out.println("看家");
    }
}

定义测试类:


public class Test {
    public static void main(String[] args) {
        // 向上转型
        Animal a = new Cat();
        a.eat(); // 调用的是 Cat 的 eat
        // 向下转型
        Cat c = (Cat)a;
        c.catchMouse(); // 调用的是 Cat 的 catchMouse
    }
}

注意:此处在转换时,有时会出现转换异常的情况,例如:

public class Test {
    public static void main(String[] args) {
        // 向上转型
        Animal a = new Cat();
        a.eat(); // 调用的是 Cat 的 eat
        // 向下转型
        Dog d = (Dog)a;
        d.watchHouse(); // 调用的是 Dog 的 watchHouse 【运行报错】
    }
}

        这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。

所以在转换前我们可以先做一个判断

public class Test {
    public static void main(String[] args) {
        // 向上转型
        Animal a = new Cat();
        a.eat(); // 调用的是 Cat 的 eat
        // 向下转型
        if (a instanceof Cat){
            Cat c = (Cat)a;
            c.catchMouse(); // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;
            d.watchHouse(); // 调用的是 Dog 的 watchHouse
        }
    }
}

 六、总结

        以上就是小编收集的关于java的封装、继承、多态的知识点了,有问题的地方欢迎评论交流呀,期待和各位一起变强呀!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java系列——封装、继承、多态初了解 的相关文章

随机推荐

  • 简单的视频剪辑教程:使用win10自带的工具剪切和合并视频

    剪切视频 右键视频文件以 照片 的方式打开视频 如同 点击右上角的编辑 如下图 选择 剪裁 进度条会看到绿球和白球 绿球是当前视频播放的位置 进度条两端都有白球 白球内进度条是要保存的视频 如下图是保存的视频 之后把文件保存 合并视频 找到
  • python dialog使用_dialog的使用方法

    dialog的使用方法 发布时间 2020 06 03 14 09 01 来源 亿速云 阅读 563 作者 Leah 今天小编给大家分享的是dialog的使用方法的介绍 相信大部分人都不太了解 为了让大家更加了解 小编给大家总结了以下内容
  • 1.5 起步 - 安装 Git

    1 5 起步 安装 Git 版本说明 版本 作者 日期 备注 0 1 loon 2019 3 19 初稿 目录 文章目录 1 5 起步 安装 Git 版本说明 目录 安装 Git 1 在 Linux 上安装 2 在 Mac 上安装 Figu
  • struct iphdr IP头部与tcphdr tcp头部与linux中的struct IP IP头部

    struct iphdr IP头部 sk buff gt iphdr usr src linux 2 6 19 include linux ip h struct iphdr if defined LITTLE ENDIAN BITFIEL
  • 用Process Explorer分析进程各个线程CPU占用率

    使用Process Explorer可以很方便查看某个进程各个线程的CPU占用率 可以为排查问题提供帮助 我使用的Process Explorer版本是v16 21 64bit 使用VS 2008创建一个MFC对话框程序 在代码中创建两个线
  • ajax上传 webapi,让webapi只接受ajax请求

    AjaxOnly继承ActionFilterAttribute 代码如下 public class AjaxOnlyAttribute ActionFilterAttribute public override void OnActionE
  • 2022 MathorCup 数学建模B题思路解析

    文章目录 Mathorcup B题题目介绍 一 问题一 1 地图模型 2 路径规划 3 任务分配调度模型 二 问题二 三 问题三 1 分析 1 点冲突 2 边冲突 2 冲突处理及模型评价 Mathorcup B题题目介绍 B题无人仓的搬运机
  • Visual Leak Detector(vld)无法显示内存泄露打印信息解决办法

    如果使用vld时 没有任何泄露信息输出时 关注编译过程是否出现编译警告 warning C4627 include
  • List 转换为 List<实体类>

    步骤 1 for循环遍历list 2 用Object 数组接受每个Object对象 3 将Object 里的参数取出放入 实体对象中 4 将实体对象放进 list lt 实体类 gt 中 String sql SELECT FROM dep
  • JAVA获取对象类名

    对象名 getClass 与类名 class所得到的字符串相同 String a new String aaa System out println a getClass String class 返回true
  • 关于fatal error LNK1104: cannot open file 'uuid.lib'的问题

    关于fatal error LNK1104 cannot open file uuid lib 的问题 今天想要将cl命令配置到命令行中使用 在网上找了一下资料 按照http www oschina net question 234345
  • GPIO的速度的理解

    一 GPIO模式配置 1 输入 输出模式 参考stm32手册 2 GPIO输出模式下 几种速度的区别 1 GPIO 引脚速度 GPIO Speed 2MHz 10MHz 50MHz 又称输出驱动电路的响应速度 芯片内部在I O口的输出部分安
  • 逆变器原理

    逆变器是把直流电转变为交流电的一种装置 它一般包括逆变桥 控制逻辑和滤波电路组成 主要是把各种直流源转变为交流供交流负载使用 一般直流源有蓄电池 干电池 太阳能电池等 可以应用到不间断电源 UPS 太阳能发电转换等 本次来探讨一下逆变桥的工
  • Unity游戏开发——UnityUGUI打包图集

    现在Unity中使用UGUI实现UI的越来越多 我们项目也才4 6 1升级到5 6 3对项目全面升级 5 x中UGUI已经非常成熟 各种资料各种效果都非常多 由于之前一直习惯用NGUI在使用UGUI还是比较顺利的 都是一个作者写的都是控件式
  • 货币战争

    中国人写的关于货币的书籍 卖的比较好 关于xx家族的阴谋论 金融控制了世界 现在xx家族的财富得有多少 有许多人反驳这本书中写的内容 xx家族早已没落了 但是写的还是不错的 推荐推荐 2013 9 29
  • esp32微型计算机,基于ESP32的几款开发板

    ESP32是乐鑫推出的一款芯片 拥有40nm的工艺 双核32位MCU 2 4GHz双模Wi Fi和蓝牙芯片 主频高达230MHz 计算能力可达600DMIPS 下面为大家介绍一些基于ESP32的开发板 1 Heartypatch 一款基于E
  • 【Kafka】docker部署Kafka集群

    目录 Kafka概述 Kafka集群docker部署流程 简述 环境准备 部署流程 参考文献 Kafka概述 以下概述Kafka内的几个核心概念 可参考官方文档 有兴趣可读 kafka apache org Topic与日志 Topic 就
  • 第四篇、UDP消息发送

    文章目录 前言 一 UDP通信操作 二 代码示例 1 UDP消息发送 总结 前言 上一篇我们共同学习了TCP文件传输 本篇我们来学习UDP消息发送 一 UDP通信操作 发送方 1 建立一个socket连接 2 建立一个包 3 发送包 4 关
  • SSL VPN

    1 SSL工作过程是什么 第一阶段 客户端首先发送client hello消息到服务端 服务端收到client hello信息后 再发送server hello消息到客户端 随机数 32位时间戳 28字节随机序列 用于计算摘要信息和预主密钥
  • Java系列——封装、继承、多态初了解

    目录 一 前言 二 封装 1 什么是封装 2 封装的特点 3 封装的使用 三 继承 1 什么是继承 2 继承的特点 3 继承的优点 4 继承的使用 4 1 继承的格式 4 2 继承的演示 4 3 成员变量 4 4 成员方法 4 5 构造方法