”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Java 中的封装与抽象:终极指南

Java 中的封装与抽象:终极指南

发布于2024-11-08
浏览:879

Encapsulation vs. Abstraction in Java: The Ultimate Guide

学习 Java 或任何面向对象编程 (OOP) 语言时,两个基本概念很突出:封装抽象。这些概念是 OOP 的关键支柱,可提高代码的可重用性、安全性和可维护性。尽管它们经常一起使用,但它们具有不同的目的。

在这篇文章中,我们将深入探讨封装和抽象之间的差异,并通过清晰的定义、示例和代码片段来帮助您了解它们在 Java 编程中的作用。让我们来分解一下吧!

什么是封装?

封装是将数据(变量)和对数据进行操作的方法捆绑到单个单元(通常是类)中的过程。它向外界隐藏对象的内部状态,只允许通过公共方法进行受控访问。

封装的主要特点:

  1. 数据隐藏:内部对象数据对其他类隐藏。
  2. 访问控制:只有允许的(公共)方法才能操作隐藏数据。
  3. 提高安全性:防止外部代码直接修改内部数据。
  4. 维护方便:如果内部实现发生变化,只需要更新方法,不需要更新外部类。

Java封装的例子:

// Encapsulation in action

public class Employee {
    // Private variables (data hiding)
    private String name;
    private int age;

    // Getter and setter methods (controlled access)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

// Using the encapsulated class
public class Main {
    public static void main(String[] args) {
        Employee emp = new Employee();
        emp.setName("John Doe");
        emp.setAge(30);

        System.out.println("Employee Name: "   emp.getName());
        System.out.println("Employee Age: "   emp.getAge());
    }
}

在此示例中,Employee 类通过将其声明为私有来隐藏其字段(姓名和年龄)。像 Main 这样的外部类只能通过 getter 和 setter 方法访问这些字段,这些方法控制和验证输入/输出。


什么是抽象?

抽象是指隐藏对象复杂的实现细节并仅暴露基本特征的概念。这简化了与对象的交互并使代码更加用户友好。

抽象的主要特征:

  1. 隐藏复杂性:用户只看到自己需要的,底层代码被隐藏。
  2. 关注“内容”而不是“如何”:仅向用户提供必要的详细信息,同时隐藏实现。
  3. 帮助管理复杂性:通过提供简化的接口,有助于处理复杂的系统。
  4. 通过接口和抽象类强制执行:这些构造提供了蓝图而不暴露实现。

Java 中的抽象示例:

// Abstract class showcasing abstraction
abstract class Animal {
    // Abstract method (no implementation)
    public abstract void sound();

    // Concrete method
    public void sleep() {
        System.out.println("Sleeping...");
    }
}

// Subclass providing implementation for abstract method
class Dog extends Animal {
    public void sound() {
        System.out.println("Barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.sound();  // Calls the implementation of the Dog class
        dog.sleep();  // Calls the common method in the Animal class
    }
}

这里,抽象类Animal包含一个抽象方法sound(),该方法必须由其子类实现。 Dog 类提供了自己的 sound() 实现。这样,用户不需要担心 sound() 方法内部如何工作——他们只需调用它即可。


封装与抽象:主要区别

现在我们已经了解了定义和示例,让我们重点介绍 Java 中封装和抽象之间的主要区别:

特征 封装 抽象
目的 数据隐藏和保护内部状态 通过隐藏复杂细节来简化代码
重点 使用 getter/setter 控制对数据的访问 提供基本功能并隐藏实现
执行 使用带有私有字段的类实现 使用抽象类和接口实现
OOP 中的角色 提高安全性并保持对数据的控制 简化与复杂系统的交互
例子 私有变量和公共方法 抽象方法和接口

Java 的实际用例

何时使用封装:

  • 当您需要保护数据时:例如,在银行系统中不应直接修改账户余额。
  • 当您想要控制数据的访问方式时:确保只有允许的方法才能修改或检索数据,从而添加一层安全性。

何时使用抽象:

  • 在大型系统上工作时:在各种类和模块交互的大型项目中,抽象可以通过提供简化的接口来帮助管理复杂性。
  • 开发API时:仅向用户公开必要的细节,同时隐藏实际的实现。

封装和抽象相结合的好处

虽然封装和抽象服务于不同的目的,但它们一起工作以在 Java 中构建健壮、安全和可维护的代码。

  1. 安全性和灵活性:通过将两者结合起来,您可以确保数据受到保护(封装),同时仍然允许用户以简单的方式与其交互(抽象)。
  2. 代码可维护性:抽象隐藏了复杂性,使系统更易于管理,而封装提供了对数据的受控访问。
  3. 可重用性:这两个概念都促进代码重用——通过隔离数据进行封装,通过允许抽象方法的不同实现进行抽象。

结论:掌握 Java 中的封装和抽象

封装和抽象是面向对象编程中两个强大的概念,每个 Java 开发人员都应该掌握。虽然封装通过控制数据访问来帮助保护对象的内部状态,但抽象隐藏了系统的复杂性并仅提供必要的细节。

通过理解和应用两者,您可以构建经得起时间考验的安全、可维护和可扩展的应用程序。


本指南是否帮助您阐明 Java 中的封装和抽象?在下面的评论中分享您的想法或问题!


标签:

  • #Java
  • #OOP
  • #封装
  • #抽象
  • #Java编程

版本声明 本文转载于:https://dev.to/abhinowww/encapsulation-vs-abstraction-in-java-the-ultimate-guide-4ccf?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 表单刷新后如何防止重复提交?
    表单刷新后如何防止重复提交?
    在Web开发中预防重复提交 在表格提交后刷新页面时,遇到重复提交的问题是常见的。要解决这个问题,请考虑以下方法: 想象一下具有这样的代码段,看起来像这样的代码段:)){ //数据库操作... 回声“操作完成”; 死(); } ?> ...
    编程 发布于2025-07-03
  • 如何检查对象是否具有Python中的特定属性?
    如何检查对象是否具有Python中的特定属性?
    方法来确定对象属性存在寻求一种方法来验证对象中特定属性的存在。考虑以下示例,其中尝试访问不确定属性会引起错误: >>> a = someClass() >>> A.property Trackback(最近的最新电话): 文件“ ”,第1行, AttributeError: SomeClass...
    编程 发布于2025-07-03
  • 为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    为什么不````''{margin:0; }`始终删除CSS中的最高边距?
    在CSS 问题:不正确的代码: 全球范围将所有余量重置为零,如提供的代码所建议的,可能会导致意外的副作用。解决特定的保证金问题是更建议的。 例如,在提供的示例中,将以下代码添加到CSS中,将解决余量问题: body H1 { 保证金顶:-40px; } 此方法更精确,避免了由全局保证金重置引...
    编程 发布于2025-07-03
  • 为什么PYTZ最初显示出意外的时区偏移?
    为什么PYTZ最初显示出意外的时区偏移?
    与pytz 最初从pytz获得特定的偏移。例如,亚洲/hong_kong最初显示一个七个小时37分钟的偏移: 差异源利用本地化将时区分配给日期,使用了适当的时区名称和偏移量。但是,直接使用DateTime构造器分配时区不允许进行正确的调整。 example pytz.timezone(...
    编程 发布于2025-07-03
  • 哪种方法更有效地用于点 - 填点检测:射线跟踪或matplotlib \的路径contains_points?
    哪种方法更有效地用于点 - 填点检测:射线跟踪或matplotlib \的路径contains_points?
    在Python Matplotlib's path.contains_points FunctionMatplotlib's path.contains_points function employs a path object to represent the polygon.它...
    编程 发布于2025-07-03
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法表示的字符串时,您可能会遇到错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && ...
    编程 发布于2025-07-03
  • 如何使用组在MySQL中旋转数据?
    如何使用组在MySQL中旋转数据?
    在关系数据库中使用mySQL组使用mySQL组进行查询结果,在关系数据库中使用MySQL组,转移数据的数据是指重新排列的行和列的重排以增强数据可视化。在这里,我们面对一个共同的挑战:使用组的组将数据从基于行的基于列的转换为基于列。 Let's consider the following ...
    编程 发布于2025-07-03
  • 如何在无序集合中为元组实现通用哈希功能?
    如何在无序集合中为元组实现通用哈希功能?
    在未订购的集合中的元素要纠正此问题,一种方法是手动为特定元组类型定义哈希函数,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    编程 发布于2025-07-03
  • Python高效去除文本中HTML标签方法
    Python高效去除文本中HTML标签方法
    在Python中剥离HTML标签,以获取原始的文本表示Achieving Text-Only Extraction with Python's MLStripperTo streamline the stripping process, the Python standard librar...
    编程 发布于2025-07-03
  • 如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求模拟浏览器行为,以及伪造的用户代理提供了一个用户 - 代理标头一个有效方法是提供有效的用户式header,以提供有效的用户 - 设置,该标题可以通过browser和Acterner Systems the equestersystermery和操作系统。通过模仿像Chro...
    编程 发布于2025-07-03
  • 使用jQuery如何有效修改":after"伪元素的CSS属性?
    使用jQuery如何有效修改":after"伪元素的CSS属性?
    在jquery中了解伪元素的限制:访问“ selector 尝试修改“:”选择器的CSS属性时,您可能会遇到困难。 This is because pseudo-elements are not part of the DOM (Document Object Model) and are th...
    编程 发布于2025-07-03
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式接口中实现垂直滚动元素的CSS高度限制问题:考虑一个布局,其中我们具有与用户垂直滚动一起移动的可滚动地图div,同时与固定的固定sidebar保持一致。但是,地图的滚动无限期扩展,超过了视口的高度,阻止用户访问页面页脚。$("#map").css({ marginT...
    编程 发布于2025-07-03
  • 编译器报错“usr/bin/ld: cannot find -l”解决方法
    编译器报错“usr/bin/ld: cannot find -l”解决方法
    错误:“ usr/bin/ld:找不到-l “ 此错误表明链接器在链接您的可执行文件时无法找到指定的库。为了解决此问题,我们将深入研究如何指定库路径并将链接引导到正确位置的详细信息。添加库搜索路径的一个可能的原因是,此错误是您的makefile中缺少库搜索路径。要解决它,您可以在链接器命令中添加...
    编程 发布于2025-07-03
  • 如何同步迭代并从PHP中的两个等级阵列打印值?
    如何同步迭代并从PHP中的两个等级阵列打印值?
    同步的迭代和打印值来自相同大小的两个数组使用两个数组相等大小的selectbox时,一个包含country代码的数组,另一个包含乡村代码,另一个包含其相应名称的数组,可能会因不当提供了exply for for for the uncore for the forsion for for ytry...
    编程 发布于2025-07-03
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,可以更快地搜索这些前缀。了解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-07-03

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3