杰瑞科技汇

java private 变量

private 是 Java 访问修饰符(Access Modifier)中最严格的一个,它定义了类成员(变量和方法)的可见性范围。

核心概念:封装

理解 private 的关键在于理解面向对象编程中的一个核心原则:封装

封装 的思想是:

  1. 将数据(变量)和操作数据的方法(函数)捆绑在一起,形成一个独立的单元(即类)。
  2. 隐藏对象的内部状态,防止外部代码直接、随意地访问和修改对象的数据。
  3. 对外暴露一个受控的接口(通常是 public 的方法),让外部代码通过这个接口与对象进行交互。

private 就是实现封装最直接、最重要的工具。


private 变量的定义和作用域

当一个变量被声明为 private 时,它的作用域被严格限制在声明它的类内部

  • 在类内部:类的所有方法(包括构造方法、实例方法、静态方法)都可以直接访问这个 private 变量。
  • 在类外部:任何其他类,即使是同一个包下的类,或者试图通过创建对象来访问,都无法直接看到或修改这个 private 变量。

private 变量是类的“私事”,不对外公开。


为什么使用 private 变量?(好处)

使用 private 变量而不是 public 变量,主要有以下几个至关重要的好处:

  1. 数据保护

    • 防止外部代码将对象置于无效或不一致的状态,一个 Person 类的 age 变量,如果设为 public,任何人都可以将其设置为负数,这是不合理的,通过 private,你可以在设置方法中加入校验逻辑。
  2. 灵活性

    • 你可以在不破坏现有代码的情况下,修改类的内部实现,你可能最初用一个 String 存储日期,后来想换成 LocalDate 对象,如果日期变量是 public,所有直接访问它的代码都需要修改,但如果它是 private,你只需要修改类内部的处理逻辑,而提供给外部的 public 方法(如 getDate())保持不变,那么所有使用这个类的代码都不需要改动。
  3. 实现控制逻辑

    • 你可以在“获取”和“设置”变量时添加额外的逻辑,
      • 验证:确保新值是有效的。
      • 触发事件:当值改变时,通知其他对象。
      • 计算:返回一个计算后的值,而不是直接存储的值。

如何访问和修改 private 变量?

既然外部类不能直接访问 private 变量,那么应该如何与之交互呢?答案是:通过公共方法,通常称为 GetterSetter

  • Getter (或 Accessor):一个 public 方法,用于获取 private 变量的值,命名惯例通常是 get + 变量名(首字母大写)。
  • Setter (或 Mutator):一个 public 方法,用于修改 private 变量的值,命名惯例通常是 set + 变量名(首字母大写)。

代码示例

让我们通过一个经典的 BankAccount 类来演示。

不使用 private 的问题

// 问题代码:不使用 private
public class BadBankAccount {
    public double balance; // 余额是公开的
    public BadBankAccount(double initialBalance) {
        this.balance = initialBalance;
    }
}
public class Main {
    public static void main(String[] args) {
        BadAccount account = new BadAccount(1000.0);
        System.out.println("初始余额: " + account.balance); // 可以直接访问
        account.balance = -500.0; // 任何人都可以将余额设置为负数!
        System.out.println("恶意修改后的余额: " + account.balance); // 程序逻辑被破坏
    }
}

这段代码的 balance 变量非常脆弱,可以被随意修改,导致对象状态无效。

使用 private 和 Getter/Setter 的正确方式

// 正确的代码:使用 private 和封装
public class BankAccount {
    // 1. 将变量声明为 private,外部无法直接访问
    private double balance;
    // 构造方法也是类内部的方法,所以可以访问 private 变量
    public BankAccount(double initialBalance) {
        // 在构造方法中加入初始校验
        if (initialBalance >= 0) {
            this.balance = initialBalance;
        } else {
            this.balance = 0;
            System.out.println("初始余额不能为负数,已自动设置为 0。");
        }
    }
    // 2. 提供 public 的 Getter 方法来获取余额
    public double getBalance() {
        return this.balance;
    }
    // 3. 提供 public 的 Setter 方法来修改余额,并加入控制逻辑
    public void deposit(double amount) {
        if (amount > 0) {
            this.balance += amount;
            System.out.println("存款成功,当前余额: " + this.balance);
        } else {
            System.out.println("存款金额必须为正数。");
        }
    }
    public void withdraw(double amount) {
        if (amount > 0 && amount <= this.balance) {
            this.balance -= amount;
            System.out.println("取款成功,当前余额: " + this.balance);
        } else {
            System.out.println("取款金额无效或余额不足。");
        }
    }
}
// Main 类来测试
public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000.0);
        // System.out.println(account.balance); // 编译错误!无法直接访问 private 变量
        // 必须通过公共方法来操作
        System.out.println("当前余额: " + account.getBalance());
        account.deposit(500.0);  // 存款 500
        account.withdraw(200.0); // 取款 200
        // 尝试进行非法操作
        account.withdraw(2000.0); // 会失败,因为余额不足
        account.deposit(-100.0);  // 会失败,因为存款金额为负
        System.out.println("最终余额: " + account.getBalance());
    }
}

在这个正确的例子中:

  • balanceprivate 的,受到了保护。
  • 外部代码无法直接修改 balance,必须通过 deposit()withdraw() 这些方法。
  • 这些方法内部包含了业务逻辑(检查金额是否为正、是否足够等),确保了 balance 的值始终是有效和合理的。

private 与其他访问修饰符的比较

修饰符 同一类中 同一包中 不同包的子类 全局
public ✔️ ✔️ ✔️ ✔️
protected ✔️ ✔️ ✔️
default (无修饰符) ✔️ ✔️
private
  • public: 公开的,谁都能用。
  • protected: 受保护的,本包内和子类可以用。
  • default (包私有): 同一个包内的类可以访问。
  • private: 私有的,只有自己(本类)能用。

private 变量是 Java 面向对象编程的基石。

  • 它强制实现封装,隐藏了类的内部数据。
  • 它保护了数据的完整性和一致性,防止外部代码进行非法修改。
  • 它提高了代码的灵活性和可维护性,使得类的内部实现可以被安全地修改。

最佳实践:在 Java 中,除非有非常特殊且充分的理由,否则几乎所有的实例变量都应该声明为 private,然后通过精心设计的 public getter 和 setter 方法来提供受控的访问,这是编写健壮、可维护、高质量 Java 代码的标准做法。

分享:
扫描分享到社交APP
上一篇
下一篇