面向对象 04:三大特性之——封装,封装的含义和作用,以及在 Java 中的使用方式,附完整的测试案例代码

一、前言

记录时间 [2024-05-11]

系列文章简摘:
面向对象 01:Java 面向对象相关内容整体概述
面向对象 02:区分面向过程与面向对象,类和对象的关系
面向对象 03:类与对象的创建、初始化和使用,通过 new 关键字调用构造方法,以及创建对象过程的内存分析

更多 Java 相关文章,请参考专栏哦。

本文讲述面向对象编程的三大特性之——封装。通过案例分析,简单介绍了封装的含义和作用,以及在 Java 中如何使用封装。


面向对象编程(Object-Oriented Programming, OOP)的三大特性是封装、继承和多态,这三大特性是 OOP 的基础,为设计灵活、可维护和可扩展的软件系统提供了核心机制。

这三个特性共同构成了面向对象编程的基础,使开发者能够设计出高内聚、低耦合的软件系统,促进了软件工程的高效管理和复杂问题的有效解决。

  • 高内聚:一个模块内部各个组成部分(如类的方法、函数、变量等)之间应该紧密关联,共同完成一个具体且单一的功能,不允许外部干涉。
  • 低耦合:各模块之间的依赖关系应该尽可能地减少和简化,一个模块应尽量少地依赖其他模块,模块之间的接口应清晰、简单,且只暴露必要的功能给外部使用。

二、封装概述

封装的基本思想:将对象的状态(数据成员,即属性)和行为(成员方法,即操作数据的方法)捆绑在一起,并对外界隐藏其内部实现细节的过程。

实现方式:在 Java 等面向对象编程语言中,封装是通过访问修饰符(如 publicprivateprotected 等)、构造器、gettersetter 方法等机制来实现的。通过这些手段,开发者可以精确控制类的哪些部分对外界开放,哪些部分保持内部私有。

封装的作用:封装不仅保护了数据的完整性,还提高了代码的模块化程度,使得代码更容易理解、维护和重用。具体如下。

  • 信息隐藏:将对象的内部细节(某些属性、方法)设置为私有 private,只暴露有限的公共接口(如 gettersetter 方法)供外部使用,防止外部代码直接访问和修改这些内部状态。从而减少意外修改数据的风险,增加程序的健壮性。
  • 模块化:封装促进了代码的模块化,使得每个对象成为一个独立的单元,可以单独开发、测试和维护。这不仅简化了代码的复杂性,也提高了代码的可复用性。
  • 易于使用:封装简化了对象的接口,使得用户不需要了解对象内部复杂的实现细节就能使用它。用户只需要知道对象能做什么(通过其提供的方法),而不是怎么做,这符合黑盒设计原则
  • 增强安全性:限制对对象内部数据的直接访问,可以实施更精细的控制逻辑,如数据验证,确保数据的完整性和一致性。
  • 提高可维护性和扩展性:由于内部实现细节对外部是隐藏的,当需要修改对象内部实现时,不会影响到使用该对象的其他代码,这使得软件更容易维护和升级。同时,良好的封装也为后续添加新功能提供了便利。

三、如何实现封装

在 Java 中,实现封装主要依靠以下几个关键技术手段:访问修饰符、gettersetter 方法、构造器等。

1. 访问修饰符

  • private:这是封装的核心,用于限制成员变量和方法的访问权限,使其仅对类内部可见。这可以防止外部代码直接访问和修改内部状态。
  • public:用于公开类、方法或变量,使其对所有类可见。
  • protected:允许同一包内的类以及所有子类访问。
  • 默认(没有显式修饰符):允许同一包内的类访问。

2. Getter 和 Setter 方法

  • Getter 方法:获取器,用于返回私有成员变量的值,让外部可以读取但不能直接修改这些值。
  • Setter 方法:设置器,用于设置私有成员变量的值,通常会加入数据验证逻辑,确保数据的合法性。

3. 构造器

构造器用于创建对象时初始化成员变量,可以是无参构造器或带参数的构造器,通过构造器可以控制对象创建时的必要条件和初始化状态。

(构造器部分在上一篇文章中有详细阐述)


四、封装案例分析

假设有一个 BankAccount 类,我们希望封装账户余额,仅通过特定方法暴露余额的读取和更新。

首先,在这个类中,成员变量 balance 是私有的,不能被其他类直接访问。

// 私有成员变量,余额
private double balance; 

想要访问这个内部变量,需要通过一些方法。


1. 构造方法初始化

使用 new 关键字实例化对象时,会调用对应的构造方法。

BankAccount bankAccount = new BankAccount(500);

可以通过该方法存入金额。如果初始化余额 >=0,说明金额是合法的,存入私有变量 balance;反之,则不合法,返回错误。

// 构造器
public BankAccount(double initialBalance) {// 如果初始化余额大于等于 0 ,合法,将值赋给 balanceif (initialBalance >= 0) {balance = initialBalance;} else {// 如果初始化余额小于 0 ,不合法,抛出异常throw new IllegalArgumentException("Initial balance cannot be negative.");}}

2. Getter / Setter 方法

Getter 方法用于返回私有成员变量的值;Setter 方法用于设置私有成员变量的值。

// Getter 方法
public double getBalance() {return balance;
}// Setter 方法
public void setBalance(double balance) {// 与构造方法类似,可以在前面增加一些判断条件this.balance = balance;
}

使用 Getter 方法获取余额:

// Getter 方法获取余额
System.out.println(bankAccount.getBalance());

Setter 方法用于设置余额的值,与构造方法类似,具体使用如下:

// Setter 方法设置余额的值
bankAccount.setBalance(600);

3. 存入金额

Setter 方法用于修改变量的值,存入 / 取出金额就是相当于让金额增加,也算是一种修改。

因此,存入 / 取出金额也需要使用 Setter 方法。

存入金额方式:写入需要存入的金额,然后加到原来的余额上,模拟追加存款

// Setter 方法,存入金额
public void deposit(double amount) {// 加入数据验证,存入金额需要大于 0if (amount > 0) {// 加到原来的余额上,模拟追加存款balance += amount;} else {// 金额不合法,抛出异常throw new IllegalArgumentException("Deposit amount must be positive.");}
}

具体使用方式:

// 模拟追加存款
bankAccount.deposit(200);
System.out.println("追加存款后:" + bankAccount.getBalance());

4. 取出金额

取出金额方式:写入需要取出的金额,然后从原先的金额上面扣除,模拟取出部分存款

// Setter 方法,取出金额
public void withdraw(double amount) {// 判断:取出金额的数量不能超过存款,且大于 0if (amount > 0 && amount <= balance) {// 从原先的金额上面扣除balance -= amount;} else {// 金额不合法,抛出异常throw new IllegalArgumentException("Invalid withdrawal amount.");}
}

具体使用方式:

// 模拟取出部分存款
bankAccount.withdraw(100);
System.out.println("取出存款后:" + bankAccount.getBalance());

五、完整测试代码

1. BankAccount 类

public class BankAccount {private double balance; // 私有成员变量,余额// 构造器public BankAccount(double initialBalance) {if (initialBalance >= 0) {balance = initialBalance;} else {throw new IllegalArgumentException("Initial balance cannot be negative.");}}// Getter方法public double getBalance() {return balance;}// Setter方法
//    public void setBalance(double balance) {
//        this.balance = balance;
//    }// Setter 方法,存入金额public void deposit(double amount) {// 加入数据验证,存入金额需要大于 0if (amount > 0) {// 加到原来的余额上,模拟追加存款balance += amount;} else {// 金额不合法,抛出异常throw new IllegalArgumentException("Deposit amount must be positive.");}}// Setter 方法,取出金额public void withdraw(double amount) {// 判断:取出金额的数量不能超过存款,且大于 0if (amount > 0 && amount <= balance) {// 从原先的金额上面扣除balance -= amount;} else {// 金额不合法,抛出异常throw new IllegalArgumentException("Invalid withdrawal amount.");}}
}

2. 测试类

public class Application {public static void main(String[] args) {// new 实例化对象// 初始化余额为 500BankAccount bankAccount = new BankAccount(500);// Getter 方法获取余额System.out.println("当前余额为:" + bankAccount.getBalance());// Setter 方法设置余额的值
//        bankAccount.setBalance(600);// 模拟追加存款bankAccount.deposit(200);System.out.println("追加存款后:" + bankAccount.getBalance());// 模拟取出部分存款bankAccount.withdraw(100);System.out.println("取出存款后:" + bankAccount.getBalance());}
}

六、总结

本文讲述面向对象编程的三大特性之——封装。通过案例分析,简单介绍了封装的含义和作用,以及在 Java 中如何使用封装


一些参考资料

狂神说 Java 零基础:https://www.bilibili.com/video/BV12J41137hu/
TIOBE 编程语言走势: https://www.tiobe.com/tiobe-index/
Typora 官网:https://www.typoraio.cn/
Oracle 官网:https://www.oracle.com/
Notepad++ 下载地址:https://notepad-plus.en.softonic.com/
IDEA 官网:https://www.jetbrains.com.cn/idea/
Java 开发手册:https://developer.aliyun.com/ebook/394
Java 8 帮助文档:https://docs.oracle.com/javase/8/docs/api/

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

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

相关文章

@vueuse/core 常用方法

createGlobalState | VueUse中文文档 <template><div class"container"><div>{{ x }}-{{ y }}</div><div>{{ store }}</div><div><button click"addNum">add-{{ counter }}</button></div>…

计算机vcruntime140.dll找不到如何修复,分享5种靠谱的修复教程

当您在运行某个应用程序或游戏时遇到提示“找不到vcruntime140.dll”&#xff0c;这通常意味着系统中缺少了Visual C Redistributable for Visual Studio 2015或更高版本的一个重要组件。这个错误通常发生在运行某些程序时&#xff0c;系统无法找到所需的动态链接库文件。小编将…

【JAVA】数组的应用场景

1 保存数据 public static void main(String[] args) {int[] array {1, 2, 3};for(int i 0; i < array.length; i){System.out.println(array[i] " ");} } 2 作为函数的参数 1. 参数传基本数据类型 public static void main(String[] args) {int num 0;fu…

917.仅仅反转字母(leetcode)

给你一个字符串 s &#xff0c;根据下述规则反转字符串&#xff1a; 所有非英文字母保留在原有位置。所有英文字母&#xff08;小写或大写&#xff09;位置反转。 返回反转后的 s 。 示例 1&#xff1a; 输入&#xff1a;s "ab-cd" 输出&#xff1a;"dc-ba&quo…

手撸XXL-JOB(三)——本地定时任务管理平台

引言 在XXL-JOB中&#xff0c;有一个xxl-job-admin项目&#xff0c;这个就相当于定时任务的调度平台&#xff0c;我们参考XXL-JOB&#xff0c;也添加这么一个调度平台&#xff0c;由于篇幅有限&#xff0c;我们先实现一个本地的定时任务调度平台&#xff0c;至于如何调用远程的…

蓝桥杯备战13.赦免战俘

P5461 赦免战俘 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> using namespace std; #define endl \n //#define int long long const int N 2e510; int n,p1,a[1050][1050]; void di(int x,int l,int q)//x是正方形边长&#xff0c;l、q是正方…

算法练习day8

反转字符串 代码随想录 0344.反转字符串 344. 反转字符串 - 力扣&#xff08;LeetCode&#xff09; &#xff08;用时&#xff1a;0.05小时&#xff09; 思路 这道题很简单也很经典。 字符串的反转方法有很多&#xff0c;我这里是用for循环通过数组长度和下标计算来交换。…

【小积累】@Qualifier注解

今天在看rabbitMQ的时候需要绑定交换机和队列&#xff0c;交换机和队列都已经注入到spring容器中&#xff0c;写了一个配置类&#xff0c;使用了bean注解注入的。所以这时候绑定的时候需要使用容器中的交换机和队列&#xff0c;必须要使用Qualifier去确定是容器中的哪个bean对象…

vue2 v-model 绑定不同的表单元素,绑定不同表单元素的属性

输入框 input:text --> value文本域 textarea --> value复选框 input:checkbox --> checked单选框 input:radio --> checked下拉菜单 select–> value 1、绑定输入框 input typetext / password / number <!--绑定的是 typetext / password 的 value值 --…

【Unity Shader入门精要 第7章】基础纹理补充内容:MipMap原理

1.纹理采样 我们对纹理采样进行显示的过程&#xff0c;可以理解为将屏幕上的一个像素&#xff08;下文用像素表示&#xff09;映射到纹理上的一个像素&#xff08;下文用纹素表示&#xff09;&#xff0c;然后用纹理上的这个像素的颜色进行显示。 理想情况下&#xff0c;屏幕…

Optional用法

说明&#xff1a;Optional和Stream一样&#xff0c;是Java8引入的特性&#xff0c;本文介绍Optional的几个实际用法。Steam流使用&#xff0c;参考下面这篇文章&#xff1a; Stream流使用 使用 1.保证值存在 // 1.保证值存在&#xff0c;pageNumber&#xff0c;pageSizeInte…

HTTP基础概念和HTTP缓存技术

什么是HTTP HTTP是超文本传输协议&#xff0c;主要分为三个部分&#xff1a;超文本、传输、协议。 超文本是指&#xff1a;文字、图片、视频的混合体。传输是指&#xff1a;点与点之间的信息通信。协议是指&#xff1a;通信时的行为规范或约定 HTTP常见字段 字段名 解释 例…

【代码随想录37期】Day07四数相加Ⅱ、赎金信、三数之和、四数之和

四数相加Ⅱ 代码随想录 454. 四数相加 II - 力扣&#xff08;LeetCode&#xff09; v1.0:直接超时&#xff0c;完全可以把0 - nums1[i]-nums2[j]作为一组&#xff0c;避免了三重循环&#xff01; class Solution { public:int fourSumCount(vector<int>& nums1, v…

收集垃圾的最少总时间- (LeetCode)

题目 给你一个下标从 0 开始的字符串数组 garbage &#xff0c;其中 garbage[i] 表示第 i 个房子的垃圾集合。garbage[i] 只包含字符 M &#xff0c;P 和 G &#xff0c;但可能包含多个相同字符&#xff0c;每个字符分别表示一单位的金属、纸和玻璃。垃圾车收拾 一 单位的任何…

SpringJPA审计

1.实体类 package com.tiger.jpatest.entity;import jakarta.persistence.*; import lombok.Data; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifi…

图片标签 以及 常见的图片的格式

1.图片的基本使用 2.图片的常见格式 3.bmp格式

前端已死? Bootstrap--JS-jQuery

目录 Bootstrap--JS-jQuery 1 jQuery基础 介绍 基础语法&#xff1a; $(selector).action() 1.1 安装jQuery 地址 基础语法&#xff1a; $(selector).action() 2 jQuery事件 事件处理程序指的是当 HTML 中发生某些事件时所调用的方法。 jQuery常用事件 2.1 鼠标事件…

element-ui的表单中,输入框、级联选择器的长度设置

使用<el-col>控制输入框的长度 <el-form-item label"姓名" label-width"80px"><el-col :span"15"><el-input v-model"form.name" autocomplete"off"></el-input></el-col></el-form…

AI助力内容创作:让效率与质量齐飞

简述&#xff1a; 本文介绍了AI如何帮助创作者在保持内容质量的同时&#xff0c;大幅度提升生产效率的一些方法&#xff0c;希想 对大家有帮助。 一、自动化内容生成 1. 文本内容生成 使用GPT等模型&#xff1a;利用如GPT-3或GPT-4等大型语言模型&#xff0c;可以直接输入关…

linux进阶高级配置,你需要知道的有哪些(12)-rsync

1、rsync的作用 一款快速增量备份工具 支持本地复制&#xff0c;或者与其他SSH、rsync主机同步 2、配置源的两种表示方法&#xff08;服务器端&#xff09; 方法一&#xff1a;用户名主机地址&#xff1a;&#xff1a;共享模块名 方法二&#xff1a;rsync&#xff1a;//用户名…