面向对象特征一:封装性

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

 

具体修饰的结构:
外部类: 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[] 内部实 现,而对外的方法不变,我们使用者根本感觉不到它内部的修改。
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 修饰。

总结:

面向对象特征之一:封装性

1. 为什么需要封装性?
理论上:
  -`高内聚`:类的内部数据操作细节自己完成,不允许外部干涉;
  -`低耦合`:仅暴露少量的方法给外部使用,尽量方便外部调用。

通俗的说:把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。


2. 如何实现数据封装?

2.1 权限修饰符
    Java规定了4种权限修饰,分别是:private、缺省、protected、public

2.2 作用
    我们可以使用4种权限修饰来修饰类及类的内部成员。当这些成员被调用时,体现可见性的大小。

2.3 实际案例:
在题目中,我们给Animal的对象的legs属性赋值。在实际的常识中,我们知道legs不能赋值为负数的。但是如果
直接调用属性legs,是不能加入判断逻辑的。那怎么办呢?
> 将legs属性私有化(private),禁止在Animal类的外部直接调用此属性
> 提供给legs属性赋值的setLegs()方法,在此方法中加入legs赋值的判断逻辑if(legs >= 0 && legs % 2 ==0)
  将此方法暴露出去,使得在Animal类的外部调用此方法,对legs属性赋值。
> 提供给legs属性获取的getLegs()方法,此方法对外暴露。使得在Animal类的外部还可以调用此属性的值。


2.4 4种权限具体使用
《见课件》

> 类:只能使用public、缺省修饰
> 类的内部成员:可以使用4种权限修饰进行修饰。

2.5 开发中4种权限使用频率的情况:
   比较高:public、private
   比较低:缺省、protected

3. 封装性的体现
> 场景1:私有化(private)类的属性,提供公共(public)的get和set方法,对此属性进行获取或修改
> 场景2:将类中不需要对外暴露的方法,设置为private.
> 场景3:单例模式中构造器private的了,避免在类的外部创建实例。(放到static关键字后讲)


 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python图像界面改左上角窗口的的icon图标

目录 问题描述 解决办法 展示成功 结语 问题描述 Traceback (most recent call last): File "d:\桌面\python项目\py_boomer-master\py_boomer-master\微信公众号.py", line 20, in <module> window.iconbitmap(D:/桌面/python项目/3.png) # Correc…

主流电商平台api接口实时数据返回

主流电商平台的API接口可以实时返回一些常用的数据&#xff0c;包括但不限于以下几种&#xff1a; 商品数据&#xff1a;可以获取平台上的商品信息&#xff0c;包括商品名称、价格、库存等。 订单数据&#xff1a;可以获取用户下单的订单信息&#xff0c;包括订单号、下单时间…

快速识别PLC通讯中的两种主要应用方式

在工业自动化领域&#xff0c;PLC扮演着至关重要的角色。然而&#xff0c;许多人在初次接触PLC通讯时&#xff0c;常因其复杂性而感到困扰。事实上&#xff0c;PLC的通讯并不如人们想象中的那么神秘&#xff0c;它主要只有两种类型&#xff1a;一种是需要编写代码的通讯方式&am…

python coding with ChatGPT 专题1 | 树的直径

文章目录 定义题目特点 树的表示字典存储邻接表TreeNode类 深度优先 &#xff08;两次DFS法&#xff09;动态规划 &#xff08;树形DP&#xff09;优势 相似题目参考资料 定义 树上任意两节点之间最长的简单路径即为树的「直径」。 题目 给定一棵树&#xff0c;求出这棵树的…

vue3+ts | axios 二次封装

安装 pnpm i axios axios 二次封装 // 实用性工具文件 放于 utils文件中 // 对axios函数库进行二次封装&#xff1f; // 二次封装的目的&#xff1f;利用axios请求、响应拦截器 import axios from axios// axios.create 创建一个axios实例&#xff1a;可以设置基础路径&a…

探索数据结构:链式队与循环队列的模拟、实现与应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 队列的定义 队列&#xff08;queue&#xff09;是一种只允许在一端进…

原来这就是线程安全(一)

TOC 一:什么是线程不安全?? 先看一段代码: public class Demo1 {public static int count 0;public static void main(String[] args) throws InterruptedException {Thread t1new Thread(()->{for (int i 0; i < 50000; i) {count;}});Thread t2new Thread(()-&g…

Linux-进程控制

&#x1f30e;进程控制【上】 文章目录&#xff1a; 进程控制 为什么要有地址空间和页表 程序的内存       程序申请内存使用问题 写时拷贝与缺页中断 父子进程代码共享       为什么需要写时拷贝       页表的权限位       缺页中断 退出码和错误码…

P3369 【模板】普通平衡树(splay 算法)

题目描述 您需要写一种数据结构&#xff08;可参考题目标题&#xff09;&#xff0c;来维护一些数&#xff0c;其中需要提供以下操作&#xff1a; 插入一个数 x。删除一个数 x&#xff08;若有多个相同的数&#xff0c;应只删除一个&#xff09;。定义排名为比当前数小的数的…

Pytorch从零开始实战22

Pytorch从零开始实战——CycleGAN实战 本系列来源于365天深度学习训练营 原作者K同学 内容介绍 CycleGAN是一种无监督图像到图像转换模型&#xff0c;它的一个重要应用领域是域迁移&#xff0c;比如可以把一张普通的风景照变化成梵高化作&#xff0c;或者将游戏画面变化成真…

2024软件设计师备考讲义——UML(统一建模语言)

UML的概念 用例图的概念 包含 <<include>>扩展<<exted>>泛化 用例图&#xff08;也可称用例建模&#xff09;描述的是外部执行者&#xff08;Actor&#xff09;所理解的系统功能。用例图用于需求分析阶段&#xff0c;它的建立是系统开发者和用户反复…

4G/5G防爆布控球

#防爆布控球 #远程实时监控 #移动应急指挥 #高清图像采集 #防爆安全认证 4G/5G防爆布控球 M130-EX防爆布控球是针对石化装置、石油平台、燃气、化工、制药、煤炭、冶炼、船舶制造、纺织等易燃易爆环境及危险场所而开发设计的防爆智能一体化电气设备。 产品型号&#xff1a;M13…

Antd Vue3 使用 Anchor 锚点组件记录

项目场景 客户要求做一个表单页面&#xff0c;表单数据分为三步&#xff0c;每一步骤是一个单独的 Vue 组件&#xff0c;表单上方需要使用锚点组件实现锚点定位到每一步的功能。 代码总览 <template><div class"guided-form-content-wrapper"><!-- …

CKS之Kubernetes审计日志

目录 概述 审计事件阶段 审计日志级别 None Metadata Request RequestResponse 审计日志的使用 步骤1&#xff1a;配置审计策略文件 步骤2&#xff1a;配置API Server 步骤3&#xff1a;配置日志存储 注意事项 审计策略与规则 审计日志样例 使用场景 概述 Kube…

一、JAVA集成海康SDK

JAVA集成海康SDK 文章目录 JAVA集成海康SDK前言一、项目依赖 jar1. examples.jar2. 项目依赖 jna.jar,可以通过 maven依赖到。二、集成SDK1.HcNetSdkUtil 海康 SDK封装类2.HCNetSDK3.Linux系统集成SDK三、总结前言 提示:首先去海康官网下载 https://open.hikvision.com/dow…

stable diffusion如何下载模型?

文件夹里面有14个模型&#xff0c;把这些模型复制到SD文件夹里 具体位置:SD文件>models>ControlNet

【C/C++】从零开始认识C++历程-启航篇

文章目录 &#x1f4dd;前言&#x1f320; 什么是C&#xff1f;&#x1f309;C的发展史 &#x1f320;C的重要性&#x1f309;语言的使用广泛度 &#x1f320;在工作领域&#x1f309; 岗位需求 &#x1f320;相关笔试题&#x1f309; 公司怎样面试C &#x1f6a9;总结 &#x…

蓝桥杯 - 小明的背包1(01背包)

解题思路&#xff1a; 本题属于01背包问题&#xff0c;使用动态规划 dp[ j ]表示容量为 j 的背包的最大价值 注意&#xff1a; 需要时刻提醒自己dp[ j ]代表的含义&#xff0c;不然容易晕头转向 注意越界问题&#xff0c;且 j 需要倒序遍历 如果正序遍历 dp[1] dp[1 - vo…

java的多态和final关键字

多态&#xff1a; 多态分为对象多态&#xff0c;行为多态 多态的前提&#xff1a; 有继承/实现关系&#xff1b;存在父类引用子类对象&#xff1b;存在方法重写&#xff1b; 注意&#xff1a;多态是对象&#xff0c;行为的多态&#xff0c;java的成员变量不谈多态 这是我写…

将Knife4j所展示请求参数和响应参数转化为TS类型声明

目标&#xff1a;在浏览器控制台输入js代码&#xff0c;将读取页面所展示的请求参数和响应参数&#xff0c;将他们转化为TS的类型声明&#xff0c;并在控制台中输出出来。 将Knife4j所展示请求参数和响应参数转化为TS类型声明 1 找到所需要的元素节点2 转化元素节点3 封装成函…