面向对象编程(基础)9:封装性(encapsulation)
目录
9.1 为什么需要封装?
而“高内聚,低耦合”的体现之一:
9.2 何为封装性?
9.3 Java如何实现数据封装
9.4 封装性的体现
9.4.1 成员变量/属性私有化
实现步骤:
成员变量封装的好处:
9.4.2 私有化方法
9.5 练习
练习1:
练习2:
9.1 为什么需要封装?
- 我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?
- 我要开车,我不需要懂离合、油门、制动等原理和维修也可以驾驶。
- 客观世界里每一个事物的内部信息都隐藏在其内部,外界无法直接操作和修改,只能通过指定的方式进行访问和修改。
随着我们系统越来越复杂,类会越来越多,那么类之间的访问边界必须把握好,面向对象的开发原则要遵循“高内聚、低耦合”。
高内聚、低耦合是软件工程中的概念,也是UNIX 操作系统设计的经典原则。
内聚,指一个模块内各个元素彼此结合的紧密程度;耦合指一个软件结构内不同模块之间互连程度的度量。内聚意味着重用和独立,耦合意味着多米诺效应牵一发动全身。
而“高内聚,低耦合”的体现之一:
高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用。
9.2 何为封装性?
所谓封装,就是把客观事物封装成抽象概念的类,并且类可以把自己的数据和方法只向可信的类或者对象开放,向没必要开放的类或者对象隐藏信息。
通俗的讲,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
9.3 Java如何实现数据封装
-
实现封装就是控制类或成员的可见性范围。这就需要依赖访问控制修饰符,也称为权限修饰符来控制。
-
权限修饰符:
public、protected、缺省、private。具体访问范围如下:
| 修饰符 | 本类内部 | 本包内 | 其他包的子类 | 其他包非子类 |
|---|---|---|---|---|
| private | √ | × | × | × |
| 缺省 | √ | √ | × | × |
| protected | √ | √ | √ | × |
| public | √ | √ | √ | √ |
- 具体修饰的结构:
- 外部类:public、缺省
- 成员变量、成员方法、构造器、成员内部类:public、protected、缺省、private

9.4 封装性的体现
9.4.1 成员变量/属性私有化
概述:私有化类的成员变量,提供公共的get和set方法,对外暴露获取和修改属性的功能。
实现步骤:
① 使用 private 修饰成员变量
private 数据类型 变量名 ;
代码如下:
public class Person {private String name;private int age;private boolean marry;
}
② 提供 getXxx方法 / setXxx 方法,可以访问成员变量,代码如下:
public class Person {private String name;private int age;private boolean marry;public void setName(String n) {name = n;}public String getName() {return name;}public void setAge(int a) {age = a;}public int getAge() {return age;}public void setMarry(boolean m){marry = m;}public boolean isMarry(){return marry;}
}
③ 测试:
public class PersonTest {public static void main(String[] args) {Person p = new Person();//实例变量私有化,跨类是无法直接使用的/* p.name = "张三";p.age = 23;p.marry = true;*/p.setName("张三");System.out.println("p.name = " + p.getName());p.setAge(23);System.out.println("p.age = " + p.getAge());p.setMarry(true);System.out.println("p.marry = " + p.isMarry());}
}
成员变量封装的好处:
- 让使用者只能通过事先预定的方法来
访问数据,从而可以在该方法里面加入控制逻辑,限制对成员变量的不合理访问。还可以进行数据检查,从而有利于保证对象信息的完整性。 便于修改,提高代码的可维护性。主要说的是隐藏的部分,在内部修改了,如果其对外可以的访问方式不变的话,外部根本感觉不到它的修改。例如:Java8->Java9,String从char[]转为byte[]内部实现,而对外的方法不变,我们使用者根本感觉不到它内部的修改。
开心一笑:
A man and woman are in a computer programming lecture. The man touches the woman's breasts."Hey!" she says. "Those are private!"The man says, "But we're in the same class!"
9.4.2 私有化方法
/*** * @Description 自定义的操作数组的工具类* @author 尚硅谷-宋红康 Email:shkstart@126.com* @version**/
public class ArrayUtil {/*** * @Description 求int型数组的最大值* @author 尚硅谷-宋红康* @param arr* @return*/public int max(int[] arr) {int maxValue = arr[0];for(int i = 1;i < arr.length;i++){if(maxValue < arr[i]){maxValue = arr[i];}}return maxValue;}/*** * @Description 求int型数组的最小值* @author 尚硅谷-宋红康* @param arr* @return*/public int min(int[] arr){int minValue = arr[0];for(int i = 1;i < arr.length;i++){if(minValue > arr[i]){minValue = arr[i];}}return minValue;}/*** * @Description 求int型数组的总和* @author 尚硅谷-宋红康* @param arr* @return*/public int sum(int[] arr) {int sum = 0;for(int i = 0;i < arr.length;i++){sum += arr[i];}return sum;}/*** * @Description 求int型数组的元素的平均值* @author 尚硅谷-宋红康* @param arr* @return*/public int avg(int[] arr) {int sumValue = sum(arr);return sumValue / arr.length;}// 创建一系列重载的上述方法// public double max(double[] arr){}// public float max(float[] arr){}// public byte max(byte[] arr){}/*** * @Description 遍历数组* @author 尚硅谷-宋红康* @param arr*/public void print(int[] arr) {for(int i = 0;i < arr.length;i++){System.out.print(arr[i] + " ");}System.out.println();}/*** * @Description 复制数组arr* @author 尚硅谷-宋红康* @param arr* @return*/public int[] copy(int[] arr) {int[] arr1 = new int[arr.length];for(int i = 0;i < arr.length;i++){arr1[i] = arr[i];}return arr1;}/*** * @Description 反转数组* @author 尚硅谷-宋红康* @param arr*/public void reverse(int[] arr) {for(int i = 0,j = arr.length - 1;i < j;i++,j--){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}/*** * @Description 数组的排序* @author 尚硅谷-宋红康* @param arr* @param desc 指明排序的方式。 ascend:升序 descend:降序*/public void sort(int[] arr,String desc) {if("ascend".equals(desc)){//if(desc.equals("ascend")){for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;swap(arr,j,j+1);}}}}else if ("descend".equals(desc)){for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] < arr[j + 1]) {
// int temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;swap(arr,j,j+1);}}}}else{System.out.println("您输入的排序方式有误!");}}private void swap(int[] arr,int i,int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}/*** * @Description 查找指定的value值在arr数组中出现的位置* @author 尚硅谷-宋红康* @param arr* @param value* @return 返回value值出现的位置 或 -1:未找到*/public int getValue(int[] arr, int value) {//方法:线性查找for(int i = 0;i < arr.length;i++){if(value == arr[i]){return i;}}return - 1;}
}
注意:
开发中,一般成员实例变量都习惯使用private修饰,再提供相应的public权限的get/set方法访问。
对于final的实例变量,不提供set()方法。(后面final关键字的时候讲)
对于static final的成员变量,习惯上使用public修饰。
9.5 练习
练习1:
创建程序:在其中定义两个类:Person和PersonTest类。定义如下:
用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。在PersonTest类中实例化Person类的对象b,调用setAge()和getAge()方法,体会Java的封装性。

练习2:
自定义图书类。设定属性包括:书名bookName,作者author,出版社名publisher,价格price;方法包括:相应属性的get/set方法,图书信息介绍等。
相关文章:
面向对象编程(基础)9:封装性(encapsulation)
目录 9.1 为什么需要封装? 而“高内聚,低耦合”的体现之一: 9.2 何为封装性? 9.3 Java如何实现数据封装 9.4 封装性的体现 9.4.1 成员变量/属性私有化 实现步骤: 成员变量封装的好处: 9.4.2 私有化…...
fate-serving-server增加取数逻辑并源码编译
1.什么是fate-serving-server? FATE-Serving 是一个高性能、工业化的联邦学习模型服务系统,专为生产环境而设计,主要用于在线推理。 2.fate-serving-server源码编译 下载fate-serving-serving项目(GitHub - FederatedAI/FATE-Serving: A scalable, h…...
循环队列、双端队列 C和C++
队列 目录 概念 实现方式 顺序队列 循环队列 队列的数组实现 用循环链表实现队列 STL 之 queue 实现队列 STL 之 dequeue 实现双端队列 概念 队列是一种特殊的线性表,它只允许在表的前端(称为队头,front)进行删除操作…...
正则表达式(语法+例子)
文章目录一、介绍二、语法1、匹配字符2、表示数量的字符3、边界字符4、其他字符5、转义字符三、例子1、邮箱2、用逗号分隔的数字集合1,23、允许一位小数4、20yy-mm-dd日期格式5、手机号6、匹配html、xml标签一、介绍 正则表达式(Regular Expression)&am…...
Properties和IO流集合的方法
方法名说明void load(InputStream inStream)从输入字节流读取属性列表(键和元素)void load(Reader reader)从输入字符流读取属性列表(键和元素对)void store(OutputStream out,String comments)将此属性列表(键和元素对…...
python 生成器、迭代器、动态新增属性及方法
目录 一、生成器 1、生成器定义 2、生成器存在的意义 3、创建生成器方式一(生成器表达式) 4. 创建生成器方式二(生成器函数) 1. 生成器函数 2. 生成器函数的工作原理 5. 总结 1. 什么是生成器 2. 生成器特点 二、迭代器…...
Java处理JSON
Java处理json有很多种方法,在这里总结一下。 1 Jackson Spring MVC 默认采用Jackson解析Json,出于最小依赖的考虑,也许Json解析第一选择就应该是Jackson。 1.1 引入的包 Jackson核心模块由三部分组成:jackson-core、jackson-a…...
58-Map和Set练习-LeetCode692前k个高频单词
题目 给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。 示例 1: 输入: words ["i", "love", …...
线程生命周期及五种状态
文章目录一、线程生命周期及五种状态1、New(初始化状态)2、Runnable(就绪状态)3、Running(运行状态)4、Blocked(阻塞状态)5、Terminated(终止状态)二、线程基本方法1、线程等待(wait)2、线程睡眠(sleep)3、…...
OBCP第八章 OB运维、监控与异常处理-灾难恢复
灾难恢复是指当数据库中的数据在被有意或无意破坏后复原数据库所需要执行的活动 回收站:回收站在原理上说就是一个数据字典表,放置用户删除的数据库对象信息。用户删除的东西被放入回收站后,其实仍然占据着物理空间,除非您手动进…...
亚马逊云科技Serverless Data:数字经济下的创新动能
Serverless时代已经到来!企业的技术架构,总是伴随着不断增长的数据与日趋复杂的业务持续演进。如何通过构建更易用的技术架构来聚焦在业务本身,而不必在底层基础设施的管理上投入过多的精力,是数据驱动型企业需要思考的重要议题。…...
【Ruby学习笔记】15.Ruby 异常
Ruby 异常 异常和执行总是被联系在一起。如果您打开一个不存在的文件,且没有恰当地处理这种情况,那么您的程序则被认为是低质量的。 如果异常发生,则程序停止。异常用于处理各种类型的错误,这些错误可能在程序执行期间发生&…...
聊聊MySQL主从延迟
文章目录 MySQL 的高可用是如何实现的呢?二、什么是主备延迟?三、主备延迟常见原因1、备库机器配置差2、备库干私活3、大事务四、主库不可用,主备切换有哪些策略?1、可靠优先2、可用优先实验一实验二3、结论MySQL 的高可用是如何实现的呢? 高可用性(high availability,缩…...
【C++从0到1】19、C++中多条件的if语句
C从0到1全系列教程 1、多条件的if语句 语法: if (表达式一) { // 表达式一为真时执行的语句。 } else if (表达式二) {// 表达式二为真时执行的语句。 } else if (表达式三) {// 表达式三为真时执行的语句。 } …… else if (表达式n) {// 表达式n为真时执行的语句。…...
【多微电网】计及碳排放的基于交替方向乘子法(ADMM)的多微网电能交互分布式运行策略研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Linux(centos7)安装防火墙firewalld及开放端口相关命令
安装firewalld 防火墙命令: yum install firewalld 安装完成,查看防火墙状态为 not running,即未运行,输入命令开启: 添加开放端口: 防火墙相关命令: 查看防火墙状态 systemctl status firewa…...
Linux部署.Net Core Web项目
本文主要记录我在Linux(Ubuntu)上部署.net core 的操作记录,也便于以后部署。 如对您有所帮助,不胜荣幸~ 文章目录前言一、准备工作1. 版本信息2. windows端web项目二、操作步骤1. Linux 配置 .net 运行环境1.1 查看最新 .net 运行环境的下载路径1.2 安装…...
【C++】STL之stack、queue的使用和模拟实现+优先级队列(附仿函数)+容器适配器详解
之前的一段时间,我们共同学习了STL中一些容器,如string、vector和list等等。本章我们将步入新阶段的学习——容器适配器。本章将详解stack、queue的使用和模拟实现优先级队列(附仿函数)容器适配器等。 目录 (一&…...
第⑦讲:Ceph集群RGW对象存储核心概念及部署使用
文章目录1.RadosGW对象存储核心概念1.1.什么是RadosGW对象存储1.2.RGW对象存储架构1.3.RGW对象存储的特点1.4.对象存储中Bucket的特性1.4.不同接口类型的对象存储访问对比2.在集群中部署RadosGW对象存储组件2.1.部署RGW组件2.2.集群中部署完RGW组件后观察集群的信息状态2.3.修改…...
从异步到promise
一,背景 1.1,js的单线程 这一切,要从js诞生之初说起,因为js是单线程的语言。 js单线程原因:作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程&…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
wpf在image控件上快速显示内存图像
wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像(比如分辨率3000*3000的图像)的办法,尤其是想把内存中的裸数据(只有图像的数据,不包…...
