Java 封装(Encapsulation)详解

封装是面向对象编程(OOP)中的一个核心概念,它涉及将数据(变量)和操作这些数据的方法(函数)捆绑成一个单一的单元或类。封装的主要目的是限制对对象某些组件的直接访问,从而保护数据的完整性,确保数据只能通过受控的方式进行访问和修改。

什么是封装?

封装是将数据和操作数据的方法打包成一个单一单元的过程。通过使用访问修饰符(如 privatepublicprotected),封装确保对象的内部状态只能通过类中的方法进行更改。这有助于提高数据的安全性和代码的可维护性。

Java 中的封装

在 Java 中,封装指的是将类的数据成员(变量)和方法(代码)集成到一个单一单元中。类的变量被隐藏起来,只能通过类中的方法进行访问。具体来说,封装涉及以下几点:

  1. 隐藏数据:将类的变量声明为 private,防止外部直接访问。
  2. 提供访问方法:通过 public 的 getter 和 setter 方法来控制对私有变量的访问。
  3. 数据验证:在 setter 方法中添加验证逻辑,确保数据的有效性。
封装的语法
<Access_Modifier> class <Class_Name> {private <Data_Members>;private <Data_Methods>;// Getter and Setter methods
}
示例

下面是一个简单的示例,展示了如何在 Java 中实现封装:

package dc;public class Main {public static void main(String[] args) {Employee e = new Employee();e.setName("Robert");e.setAge(33);e.setEmpID(1253);System.out.println("Employee's name: " + e.getName());System.out.println("Employee's age: " + e.getAge());System.out.println("Employee's ID: " + e.getEmpID());}
}package dc;public class Employee {private String name;private int empID;private int age;// Getter for namepublic String getName() {return name;}// Setter for namepublic void setName(String newName) {name = newName;}// Getter for agepublic int getAge() {return age;}// Setter for age with validationpublic void setAge(int newAge) {if (newAge > 0) {  // Ensure a valid ageage = newAge;} else {System.out.println("Please enter a valid age.");}}// Getter for empIDpublic int getEmpID() {return empID;}// Setter for empIDpublic void setEmpID(int newEmpID) {empID = newEmpID;}
}
实现 Java 封装的关键点
  1. 私有字段nameageempID 被声明为 private,不允许外部直接访问。
  2. 公共方法getName()setName()getAge()setAge()getEmpID()setEmpID() 提供了对私有字段的受控访问。
  3. 数据验证:在 setAge()setEmpID() 方法中添加了验证逻辑,确保输入的数据是有效的。

封装(Encapsulation)的优势和劣势

优势
  1. 数据保护

    • 封装通过限制对对象数据的直接访问,确保数据只能通过受控的方法进行修改,从而保护数据的完整性。
  2. 增强安全性

    • 通过隐藏内部实现细节,封装提高了安全性,防止未经授权的访问敏感数据。
  3. 简化维护

    • 封装的代码更容易维护,因为内部实现的变化不会影响其他部分的代码。
  4. 增加灵活性

    • 可以在不改变外部API的情况下修改内部组件,允许灵活地改进或更新内部逻辑。
  5. 代码复用性

    • 封装促进了模块化代码的使用,使得代码可以在程序的不同部分或未来的项目中重用。
  6. 更好的数据控制

    • 使用getter和setter方法可以应用验证和约束,确保数据的正确性。
  7. 减少复杂性

    • 封装隐藏了复杂的实现细节,使得开发者可以更轻松地处理对象,而无需了解内部工作原理。
  8. 防止意外交互

    • 封装防止了对象状态的意外或不当修改,确保所有更改都是受控和有意的。
  9. 增强可读性

    • 封装的代码通常更具可读性和可理解性,因为它提供了清晰的数据交互接口。
劣势
  1. 增加代码量

    • 封装可能需要额外的方法(如getter和setter),这会增加代码量,使其更加冗长。
  2. 性能下降

    • 通过方法间接访问数据可能会引入轻微的性能开销,与直接访问相比。
  3. 更复杂的代码结构

    • 封装有时会使代码结构变得更加复杂,尤其是在简单直接访问就足够的情况下。
  4. 维护开销

    • 管理封装的方法(尤其是复杂的验证逻辑)需要仔细的维护,这可能会更加耗时。
  5. 用户灵活性受限

    • 类的使用者可能需要更多的灵活性来访问数据,而封装只提供了预定义的方法,即使在某些情况下直接访问会更简单或更高效。

Java 封装示例

示例 1:基本数据封装

在这个示例中,我们通过将 Student 类的数据字段(如 nameage)声明为 private,并通过提供公共的 getter 和 setter 方法来实现受控访问。

// Encapsulated Student class
class Student {// Private fields (data encapsulation)private String name;private int age;// Getter for namepublic String getName() {return name;}// Setter for namepublic void setName(String name) {this.name = name;}// Getter for agepublic int getAge() {return age;}// Setter for age with validationpublic void setAge(int age) {if (age > 0) {this.age = age;} else {System.out.println("Invalid age");}}
}public class Main {public static void main(String[] args) {// Create Student objectStudent student = new Student();// Set data using settersstudent.setName("Alice");student.setAge(21);// Get data using gettersSystem.out.println("Student Name: " + student.getName());System.out.println("Student Age: " + student.getAge());}
}

输出

Student Name: Alice
Student Age: 21
示例 2:带有验证的数据封装

在这个示例中,BankAccount 类封装了 balance 字段,并提供了详细的验证逻辑,以防止设置无效值。

// Encapsulated BankAccount class
class BankAccount {// Private field to store balanceprivate double balance;// Getter for balancepublic double getBalance() {return balance;}// Setter for balance with validation (cannot be negative)public void setBalance(double balance) {if (balance >= 0) {this.balance = balance;} else {System.out.println("Invalid balance. Balance cannot be negative.");}}// Method to deposit moneypublic void deposit(double amount) {if (amount > 0) {balance += amount;} else {System.out.println("Deposit amount must be positive.");}}// Method to withdraw moneypublic void withdraw(double amount) {if (amount > 0 && amount <= balance) {balance -= amount;} else {System.out.println("Invalid withdraw amount or insufficient balance.");}}
}public class Main {public static void main(String[] args) {// Create BankAccount objectBankAccount account = new BankAccount();// Set initial balanceaccount.setBalance(1000.00);// Perform deposit and withdraw operationsaccount.deposit(500.00);account.withdraw(300.00);// Get the final balanceSystem.out.println("Final Balance: " + account.getBalance());}
}

输出

Final Balance: 1200.0
示例 3:带有多个字段的封装

在这个示例中,Employee 类封装了多个字段(如 namesalarydepartment),并确保这些字段只能通过 getter 和 setter 方法进行访问或修改。

// Encapsulated Employee class
class Employee {// Private fieldsprivate String name;private double salary;private String department;// Getter for namepublic String getName() {return name;}// Setter for namepublic void setName(String name) {this.name = name;}// Getter for salarypublic double getSalary() {return salary;}// Setter for salary with validationpublic void setSalary(double salary) {if (salary > 0) {this.salary = salary;} else {System.out.println("Invalid salary.");}}// Getter for departmentpublic String getDepartment() {return department;}// Setter for departmentpublic void setDepartment(String department) {this.department = department;}
}public class Main {public static void main(String[] args) {// Create Employee objectEmployee employee = new Employee();// Set employee details using settersemployee.setName("John Smith");employee.setSalary(70000);employee.setDepartment("Engineering");// Get and display employee details using gettersSystem.out.println("Employee Name: " + employee.getName());System.out.println("Employee Salary: " + employee.getSalary());System.out.println("Employee Department: " + employee.getDepartment());}
}

输出

Employee Name: John Smith
Employee Salary: 70000.0
Employee Department: Engineering

数据隐藏(Data Hiding)与封装(Encapsulation)在 Java 中的应用

数据隐藏(Data Hiding)

数据隐藏是一种避免访问数据成员、数据方法及其逻辑实现的过程。这可以通过使用访问修饰符来实现。Java 中有四种访问修饰符:

  1. 默认(Default)

    • 默认访问修饰符是最基本的数据隐藏形式。如果一个类没有指定访问修饰符,编译器会将其设为默认。默认访问权限类似于公共(public)访问权限,但仅限于同一个包内的类访问。
  2. 公共(Public)

    • 公共访问修饰符提供类的访问权限,使得该类可以从程序的任何地方访问。

    示例:

    package Simplilearn;class Vehicle {public int tires;public void display() {System.out.println("I have a vehicle.");System.out.println("It has " + tires + " tires.");}
    }public class Display {public static void main(String[] args) {Vehicle veh = new Vehicle();veh.tires = 4;veh.display();}
    }
    

    输出:

    I have a vehicle.
    It has 4 tires.
    
  3. 私有(Private)

    • 私有访问修饰符限制数据成员和数据方法只能在类内部访问。

    示例:

    package Simplilearn;class Student {private int rank;public int getRank() {return rank;}public void setRank(int rank) {this.rank = rank;}
    }public class School {public static void main(String[] args) {Student s = new Student();s.setRank(1022);System.out.println("Student rank is " + s.getRank());}
    }
    

    输出:

    Student rank is 1022
    
  4. 受保护(Protected)

    • 受保护访问修饰符保护类的方法和成员,类似于私有访问修饰符,但访问范围扩展到整个包,而不仅仅是类本身。

    示例:

    package Simplilearn;class Human {protected String stream;protected void display() {System.out.println("Hello, I am a " + stream + " Student");}
    }public class Student extends Human {public static void main(String[] args) {Student s = new Student();s.stream = "Computer Science and Engineering Technology";s.display();}
    }
    

    输出:

    Hello, I am a Computer Science and Engineering Technology Student
    
数据隐藏与封装的区别
数据隐藏封装
数据隐藏可以视为父过程封装是数据隐藏的一个子过程
访问修饰符通常是私有的访问修饰符可以是私有的或公共的
数据隐藏关注的是隐藏方法的实现封装关注的是将方法与数据成员结合在一起
主要目的是隐藏数据及其实现主要目的是将数据和方法组合起来

常见问题解答 (FAQs)

  1. 封装(Encapsulation)与抽象(Abstraction)有何区别?

    • 封装:封装隐藏了对象的内部状态和实现细节,通过方法只暴露必要的部分。它主要保护数据,确保数据的安全性和完整性。
    • 抽象:抽象通过关注系统的核心特征来简化复杂的系统,同时隐藏不必要的细节。它主要用于简化复杂性,使系统更易于理解和管理。
  2. 封装的类型有哪些?

    • 封装通常分为两种类型:
      • 数据封装:隐藏类的数据(属性)。
      • 功能封装:通过接口隐藏类的功能(方法),以控制数据的访问和修改方式。
  3. 现实生活中抽象和封装的例子是什么?

    • 抽象:你通过方向盘和踏板与汽车互动,而不需要了解发动机的内部机械原理。
    • 封装:发动机的内部组件被隐藏和保护,确保你不能直接修改它们,只能通过特定的控制(如油门踏板)来间接操作。
  4. 封装的类型有哪些?

    • 封装的主要类型包括:
      • 私有封装(Private Encapsulation):数据完全对外部访问隐藏,只有内部方法可以修改它。
      • 受保护封装(Protected Encapsulation):数据在类及其子类中可访问,但对程序的其他部分不可见。
  5. 为什么要使用封装?

    • 封装有以下几个主要好处:
      • 增强数据安全:通过限制对数据的直接访问,防止未经授权或意外的修改。
      • 维护数据完整性:确保数据的一致性和正确性,通过 getter 和 setter 方法控制对数据的访问。
      • 提高模块化:将类的内部实现与外部接口分离,使代码更易于维护和扩展。
      • 简化维护:通过封装,可以更容易地对类的内部实现进行修改,而不影响外部代码的运行。

总结

封装作为面向对象编程的一个原则,描述了将数据和与数据交互的方法组合成一个单一单元的过程。它常用于隐藏敏感数据,限制外部对特定属性的访问,同时允许通过公共 getter 和 setter 方法访问这些属性。封装提供了隐藏数据的基本属性,保护用户数据。

以下是本文的重点内容总结:

什么是封装?

封装(Encapsulation)是面向对象编程(OOP)的四大基本原则之一,其他三个原则分别是继承(Inheritance)、多态(Polymorphism)和抽象(Abstraction)。封装的主要目的是将数据(属性)和操作数据的方法(行为)绑定在一起,形成一个独立的单元(即类),并通过访问控制来保护数据的完整性和安全性。

封装的目的
  1. 数据保护:通过限制对类内部数据的直接访问,防止外部代码对数据的非法修改,从而保证数据的安全性和完整性。
  2. 代码组织:将相关的数据和方法组织在一起,形成一个逻辑单元,使代码更加清晰和模块化。
  3. 代码复用:封装好的类可以被多个程序或模块重用,提高代码的可重用性和可维护性。
  4. 简化接口:通过封装,可以隐藏类的内部实现细节,只暴露必要的接口给外部使用,简化了外部调用者的使用难度。
实现封装的方式

在 Java 中,封装主要通过以下几种方式实现:

  1. 访问修饰符

    • private:最严格的访问级别,只能在定义该成员的类内部访问。
    • protected:可以在同一包内或子类中访问。
    • default(无修饰符):只能在同一包内访问。
    • public:最宽松的访问级别,可以在任何地方访问。
  2. Getter 和 Setter 方法

    • Getter 方法:用于获取类的私有属性值。
    • Setter 方法:用于设置类的私有属性值。
    • 通过这些方法,可以在设置和获取属性值时添加额外的验证逻辑,确保数据的合法性。
封装的好处
  1. 数据安全:通过私有化属性,防止外部直接修改数据,确保数据的安全性。
  2. 数据完整性:通过在 setter 方法中添加验证逻辑,确保数据的合法性和一致性。
  3. 代码复用:封装好的类可以被多个程序或模块重用,提高代码的可重用性。
  4. 模块化:将相关的数据和方法组织在一起,形成一个逻辑单元,使代码更加清晰和模块化。
  5. 简化接口:通过封装,可以隐藏类的内部实现细节,只暴露必要的接口给外部使用,简化了外部调用者的使用难度。
结论

封装是 Java 中实现数据保护和代码组织的重要手段。通过合理使用访问修饰符和 getter/setter 方法,可以有效地保护类的内部数据,确保数据的安全性和完整性,同时提高代码的可重用性和可维护性。封装是面向对象编程的核心概念之一,对于编写高质量的软件系统至关重要。

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

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

相关文章

#渗透测试#SRC漏洞挖掘#深入挖掘CSRF漏洞02

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

自动驾驶革命:从特斯拉到百度,谁将主宰未来交通?

内容概要 自动驾驶技术正在经历一个前所未有的革命性变化&#xff0c;各大企业纷纷抢占这一充满潜力的新市场。以特斯拉和百度为代表的行业巨头&#xff0c;正利用各自的优势在这一技术的赛道上展开激烈竞争。特斯拉凭借其在电动汽车和自动驾驶领域的前瞻性设计与不断革新的技…

反向代理开发

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

简记Vue3(五)—— Pinia

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

C++11语法介绍(1) -- 列表初始化{},左值和右值,右值引用和移动语义,引用折叠,完美转发

目录 1.C11的发展时间线 2.列表初始化 2.1C98传统的{} 2.2C11中的{} 2.3C11中的std::initializer_list 2.3.1vector中initializer list构造的模拟实现 2.3.2以vector为例演示initializer_list版本的构造 3.右值引用和移动语义 3.1左值和右值 3.2左值引用和右值引用 3.3…

C++编程:利用环形缓冲区优化 TCP 发送流程,避免 Short Write 问题

文章目录 1. 什么是 Short Write 问题&#xff1f;2. 如何解决 Short Write 问题&#xff1f;2.1 方法 1&#xff1a;将 Socket 设置为阻塞模式2.2 方法 2&#xff1a;用户态维护发送缓冲区 3. 用户态维护发送缓冲区实现3.1 核心要点3.2 代码实现3.3 测试程序 参考文档 1. 什么…

第十三届交通运输研究(上海)论坛┆智能网联汽车技术现状与研究实践

0.简介 交通运输研究&#xff08;上海&#xff09;论坛&#xff08;简称为TRF&#xff09;是按照国际会议的组织原则&#xff0c;为综合交通运输领域学者们构建的良好合作交流平台。交通运输研究&#xff08;上海&#xff09;论坛已经成功举办了十二届&#xff0c;凝聚了全国百…

中仕公考:大三大四考公备考时间线

大三大四想要考公务员的可以借鉴以下时间线&#xff1a; 大三下学期&#xff1a; 基础看课阶段&#xff0c;刚开始先打好基础很重要&#xff0c;根据课程和教材理解知识点&#xff0c;按照模块学习&#xff0c;对考试科目的题型有深入的认识和掌握。 大四初&#xff1a; 强…

Android Studio 将项目打包成apk文件

第一步&#xff1a;选择Build -> Generate Signed APK 会出现&#xff1a; 我们选择 Create new… 然后选择你要存放密钥的地方 点击ok之后&#xff0c;则选择好了文件&#xff0c;并生成了jks文件了。 点击ok之后&#xff0c; 会出现&#xff1a; 选择release&#xf…

FFmpeg存放压缩后的音视频数据的结构体:AVPacket简介,结构体,函数

如下图的解码流程&#xff0c;AVPacket中的位置 FFmpeg源码中通过AVPacket存储压缩后的音视频数据。它通常由解复用器&#xff08;demuxers&#xff09;输出&#xff0c;然后作为输入传递给解码器。 或者从编码器作为输出接收&#xff0c;然后传递给多路复用器&#xff08;mux…

纺织品缺陷检测

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

SSM房屋销售管理系统-计算机毕业设计源码49529

摘 要 随着国民生活水平的提高&#xff0c;人们日益重视休闲旅游&#xff0c;而互联网的普及也为房屋销售管理带来了新的机遇。将房屋租赁产业与互联网相结合&#xff0c;利用 SSM 框架建设房屋销售管理系统&#xff0c;实现房屋销售管理的网络化&#xff0c;对提高国民经济发展…

【PLC一体机】触摸屏上一直显示ERR警示灯的原因和解决方法

博主之前买了一个PLC一体机&#xff0c;在触摸屏上有ERR、RUN和SYS三个显示灯&#xff08;如下图&#xff09; 其中触摸屏工作时&#xff0c;RUN显示灯会显示为绿色&#xff0c;证明触摸屏正常工作。 SYS是触摸屏上刷写PLC程序和触摸屏程序时&#xff0c;会显示为橙色&#xf…

(十四)JavaWeb后端开发——MyBatis

目录 1.MyBatis概述 2.MyBatis简单入门 3.JDBC&#xff08;了解即可&#xff09; 4.数据库连接池​ 5.lombok 6.MyBatis基本操作 7.XML映射文件 8.动态SQL 8.1 if标签 8.2 foreach标签 8.3 sql/include标签​ 1.MyBatis概述 MyBatis是一款优秀的持久层&#xff08…

Elasticsearch可视化工具Elasticvue插件用法

目录 1.打开浏览器扩展程序(示例Edge浏览器) ​2.搜索elasticvue并安装 3.打开elasticvue ​4.连接Es 5.有些浏览器无法下载安装扩展&#xff0c;例如谷歌。可以打包扩展给别的浏览器使用。 5.1打开浏览器扩展&#xff0c;打开开发人员模式&#xff0c;记住扩展程序id 5…

数据结构之排序补充

1. 非比较排序 上一篇文章我们罗列了数据结构中排序的八种方法。这八种方法都是需要比较才能实现的&#xff0c;那怎么样才可以通过非比较的方法来实现数组的排序呢&#xff1f;这里就提供一种非比较排序的方法。 具体的操作思路如下&#xff1a; 1. 先统计待比较数组arr中重…

1.62亿元!812个项目立项!上海市2024年度“科技创新行动计划”自然科学基金项目立项

本期精选SCI&EI ●IEEE 1区TOP 计算机类&#xff08;含CCF&#xff09;&#xff1b; ●EI快刊&#xff1a;最快1周录用&#xff01; 知网(CNKI)、谷歌学术期刊 ●7天录用-检索&#xff08;100%录用&#xff09;&#xff0c;1周上线&#xff1b; 免费稿件评估 免费匹配期…

危!这些高危端口再不知道问题就大了

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 下午好&#xff0c;我的网工朋友。 端口作为网络通信的基本单元&#xff0c;用于标识网络服务和应用程序。 但某些端口由于其开放性和易受攻击的…

Excel中截取中文地址转换为省、市、区

使用方法/步骤 首先我们在网页打上方方格子&#xff0c;进入官网&#xff0c;下载方方格子。 解压后进行安装&#xff0c;打开OFFIE中的EXCEL&#xff0c;可以发现新新添加一个DIY工具箱&#xff0c;其中的提取地址功能可以将字符串地址解析为省、市、区 如下图所示

引入 axios,根据 api 文档生成调用接口

起步 | Axios Docs 安装 axios npm install axios 生成 api 调用接口【可选】 https://github.com/ferdikoomen/openapi-typescript-codegen 安装 npm install openapi-typescript-codegen --save-dev 然后执行生成代码 # http://localhost:8805/api/user/v3/api-docs&a…