• 封装 Encapsulation


    封装

    再 讲 封装 前 我们 先来 补充 一下 上文 类和对象 没有 讲完的 东西

    toString


    这里我们 先来 看 这个 代码

    class Dog {
        public String name;
        public int  age;
    
        public void eat(){
            System.out.println(name +"嘎嘎猛炫");
        }
        
        public void print(){
            System.out.println("姓名 :" + name + " 年龄: " + age);
        }
        
        // 无参 构造方法
        public Dog(){
            
        }
        //带有两个参数的 构造方法
        public Dog(String name, int age){
            this.name = name;
            this.age = age;
        }
    
    }
    
    public class Test1 {
    
        public static void main(String[] args) {
            Dog dog = new Dog("小黑",3);
            dog.print();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32


    这里 我们 就能过 通过 print() 方法 将 字段/ 属性 / 成员变量 打印出来,但这里就有 一个问题 ,如果我 们的字段 非常多 ,那么 还要 一个一个的 写 吗 ?

    这里 我们的 编译器 就 非常 智能 为我们 提供 了 一个 toString方法 ,就能 帮我们直接生成 。


    下面我们 就来 尝试一下 :

    class Dog {
        public String name;
        public int  age;
    
        public void eat(){
            System.out.println(name +"嘎嘎猛炫");
        }
    
        public void print(){
            System.out.println("姓名 :" + name + " 年龄: " + age);
        }
    
        // 无参 构造方法
        public Dog(){
    
        }
        //带有两个参数的 构造方法
        public Dog(String name, int age){
            this.name = name;
            this.age = age;
        }
    
    }
    
    public class Test1 {
    
        public static void main(String[] args) {
            Dog dog = new Dog();
            System.out.println(dog);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31


    但大家 按照上面 这样 写 或 一脸蒙 为啥 要这么 写 ?

    先来看一下 执行 结果 。

    这里 我们 打印 的 是 dog 对象的 地址 ,但 介于 java的 安全 性高 , 会 对 地址 进行 修饰 ,导致 拿不到 正真 的 地址 ,只能拿到 一个哈希值 ,

    那么这 与我们 打印 字段 又有什么关系 呢??

    不要急 我们慢慢来看 这里我们 就来 看看 源码 、

    这里 我们 Ctrl 加 鼠标 左键 点 println 进入 源码

    在这里插入图片描述

    下面 继续 :Ctrl 加 鼠标 左键 进入 valueOf 中

    在这里插入图片描述

    这里我们 能看 到 我们 toString 那么 继续 再 Ctrl 加 鼠标 左键 进入 toString方法 当中 。

    在这里插入图片描述


    最后你能 发现 我们 为啥 打印 对象 为啥不能 获取 到 真正的 地址 ,而是 一个被修饰 的 地址 ,

    在这里插入图片描述


    那么 看这个到底 有啥 用呢 ?

    其实 我们 想要打印 字段 是不是 可以 重写 toString ,让 原本 打印 对象 输入 的 是 修饰的 地址 ,改为 我们需要的 字段 信息。

    class Dog {
        public String name;
        public int  age;
    
        public void eat(){
            System.out.println(name +"嘎嘎猛炫");
        }
    
        public void print(){
            System.out.println("姓名 :" + name + " 年龄: " + age);
        }
    
        // 无参 构造方法
        public Dog(){
    
        }
        //带有两个参数的 构造方法
        public Dog(String name, int age){
            this.name = name;
            this.age = age;
        }
    
        public  String  toString(){
            return "姓名 :" + name + " 年龄: " + age;
        }
    }
    
    public class Test1 {
    
        public static void main(String[] args) {
            Dog dog = new Dog();
            System.out.println(dog);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34


    在这里插入图片描述

    可以看到我们 重写 toString 后 成功 打印 出来我们需要的 字段, 但是 这里 有 疑问 ,重写 字段 不还是 要我们 自己 输入 字段吗 ,还不如 我们 直接写个 方法 ,还容易 理解。

    那么 我们 就来看一下我们 编译器 强大 的 功能 。

    在这里插入图片描述


    可以看到 这里 就 非常方便 。

    在这里插入图片描述


    眼见 的 同学 可能 发现 编译器 自动生成 的 toString 方法前面 会有一个 @Override 其实 这个 是 注解 如果我们不小心 将 toString 改掉了 ,他就会 报错 。

    看完了 toString 下面 就来 看一下我们的 封装

    封装


    概念:

    面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。

    何为封装呢?简单来说就是套壳屏蔽细节。

    比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等,让用户来和计算机进行交

    互,完成日常事务。但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件

    对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开

    机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供

    开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。

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

    知道了 封装的 概念我们 要 如何 实现封装呢??

    这里我们就先来看一下 我们的 访问权限 限定符

    访问 权限限定符

    Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控

    制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符

    在这里插入图片描述


    这里我们 先 来 了解 一下 这张图,后面 再 继承 多态 中 这张 图 还 会出现的。

    先来 看我们 最熟悉 的 public :


    public : 修饰的成员变量或者成员方法, 可以直接被其他类的调用者使用.

    简单来说 可以理解为一个人的外貌特征,谁都可以看得到

    private : 他就是 实现我们 封装的关键 字 ,被 private 修饰的成员变量或者成员方法, 不能被其他类的

    调用者使用.

    简单来说 :只有自己知道,其他人都不知道

    default : 包访问 权限, 在类中 一般不写,这里 为了 对标 其他访问权限 才写上default的

    在这里插入图片描述

    如: 在这个 类 中 color 和 month 和 year 就是包访问权限

    这里 可以简单理解 :对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了

    另外 :一般情况下成员变量设置为private,成员方法设置为public。

    稍微 了解 了 访问 权限 下面 我们就来 通过 private 来 实现我们的 封装

    private 实现封装

    下面 来 看 代码 :

    class Dog {
        private String name;
    
        public int age;
    
        private void eat() {
            System.out.println(name + "嘎嘎猛炫");
        }
    
        public void sleep() {
            System.out.println(name + "嘎嘎猛睡");
        }
    }
    
    public class Test1 {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.name = "小黑";
            dog.age = 10;
            dog.eat();
            dog.sleep();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述


    可以看到我们 的 name 和 eat 使用 dog 这个 对象 调用 的 时候 就不能 调用 ,这里 name 和 eat 就是 被 封装起来 ,我们 不能 使用 ,这里 要是 想要 使用,

    我们需要 为 name 提供 get 和 set 方法。


    这里 我们 需要 知道 被 private 修饰的 字段 或 方法, 是不可以 被 其他类 的 调用 用 者 使用 , 这里 private 会让 字段 私有化, 更加安全。

    注意 : 一般 字段 使用 private 修饰 方法 使用 public 修饰

    这里 为什么 会 更加 安全 呢 ??

    这里 就 来 举个 例子 : 有一天 有个 程序 员 写 好 了 一个类 。

    如:

    class Dog {
        public  String name;
    
        public int age;
    
        public String method;
        
        public  void eat() {
            System.out.println(name + "嘎嘎猛炫");
        }
    
        public void sleep() {
            System.out.println(name + "嘎嘎猛睡");
        }
        public void func(){
            System.out.println("这时测试 用例 ");
        }
    }
    
    public class Test1 {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.method = "小黑";
            dog.func();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26


    这里 ,他 就 发不下去 , 假设 有 很多 人 使用 他的 类 ,使用 他 公布 的 方法 。

    突然 有一天 这个程序 员 觉得 一开始 的 名字取 的并不好 这里 就 改掉 了 , 但 有没有 及时 公布 改的名字, 这时 ,使用 他 这个 类的 人 就 傻眼 , 一觉起来我 的程序 全是 bug 全是 红线 。

    class Dog {
        public  String name;
    
        public int age;
    
    //    public String method;
        // 觉得上面的 名字 不好名了
        public String agoodmethod;
    
        public  void eat() {
            System.out.println(name + "嘎嘎猛炫");
        }
    
        public void sleep() {
            System.out.println(name + "嘎嘎猛睡");
        }
    //    public void func(){
    //        System.out.println("这时测试 用例 ");
    //    }
        //这个 方法 名字 也 不好 也 改名 了 
        public void func2(){
            System.out.println("这时测试 用例 ");
        }
    }
    
    public class Test1 {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.method = "小黑";
            dog.func();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述

    下面 就来 将 一下 为啥 使用 private 更 加 安全 。

    这时 傻眼 的程序员们 ,就去 找 创建 这个类的 作者 说 ,作者 也没想都 改了 几个名字 这么 多 事情, 作为 多年的 程序员 ,他 就 立马想到了 使用private , 来修饰 他的 变量 ,然后 提供 set 和 get 方法 这样 想 改 啥名字 就 改啥名字 。

    这里我们 就 拿 字段 举例 , 方法 一般 不会 使用 private 修饰 。

    class Dog {
        private String name;
        private int age;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return this.name;
        }
    
        public int getAge() {
            return this.age;
        }
    
        @Override
        public String toString() {
            return "Dog{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    public class Test1 {
        public static void main(String[] args) {
            Dog dog = new Dog();
            dog.setAge(20);
            dog.setName("小黑 ");
            System.out.println(dog);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述


    这里 我们 就 通过 set 给我们 封装起来 的 name 个 age 赋值 了, 这里我们 还可以 通过 get 来获取 我们的 值

    ,(其实 这里 set 和 get 的 名字 可以 自己 取,但 一般都是 set 和 get set 的 中文意思 是 设置 , get的 中

    文意思 是 获取 所以 一般是 这两个 单词)。

    这个 程序员 写完 上面的 get 和 set 就 将 更新 后 的 方法 告诉 了 使用 这个 类的 使用者 们 , 此时 就算 作者 咋 改 名字 ,只要 set 和

    get 没问题, 都不会 在 影响 使用 这个 类 的 程序员们 。
    这里 就 能 看出 封装 的 好处 。

    同样 这里 set 和 get 我们 可以 通过编译器 快速生成 。
    在这里插入图片描述

    本文 结束 。

  • 相关阅读:
    物联网省/国赛AIOT智能家居全流程演示
    The 2021 CCPC Weihai Onsite E. CHASE!
    如何将几张图片转换为GIF动图?
    85. 最大矩形 java解决
    ​ Verilog UDP 基础知识分类
    Ajax跨域访问,访问成功但一直走error不走success的的问题解决
    【微机接口】第四章:宏指令程序设计
    sentinel 网关
    JAVA - 网络编程
    山西青年杂志山西青年杂志社山西青年编辑部2022年第22期目录
  • 原文地址:https://blog.csdn.net/mu_tong_/article/details/126201861