面向对象 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 ,合法,将值赋给 balance
    if (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) {
    
    // 加入数据验证,存入金额需要大于 0
    if (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) {
    
    // 判断:取出金额的数量不能超过存款,且大于 0
    if (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) {
        // 加入数据验证,存入金额需要大于 0
        if (amount > 0) {
            // 加到原来的余额上,模拟追加存款
            balance += amount;
        } else {

            // 金额不合法,抛出异常
            throw new IllegalArgumentException("Deposit amount must be positive.");
        }
    }

    // Setter 方法,取出金额
    public void withdraw(double amount) {

        // 判断:取出金额的数量不能超过存款,且大于 0
        if (amount > 0 && amount <= balance) {

            // 从原先的金额上面扣除
            balance -= amount;
        } else {
            // 金额不合法,抛出异常
            throw new IllegalArgumentException("Invalid withdrawal amount.");
        }
    }
}

2. 测试类

public class Application {

    public static void main(String[] args) {

        // new 实例化对象
        // 初始化余额为 500
        BankAccount 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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值