跳到内容

元数据卡

  • 前置知识:第7章(上)——类与构造方法
  • 预计时间:15 分钟
  • 完成标志:能将类的字段设为 private,提供 public 的 getter/setter,理解封装的意义

你能直接给 price 赋 -50?

java
myBook.price = -50.0;   // 一本书价格是负数?
myBook.isbn = null;     // ISBN 可以为空吗?

问题出在哪?调用者可以直接操作字段,没有任何约束。

老陈说:"面向对象的第一原则——封装:把数据藏起来,只暴露安全的访问方式。"

private 字段 + public 方法

Java 用访问修饰符控制可见性——private(自己)、默认(邻居)、protected(家人)、public(谁都能)。

java
class Book {
    private String title;     // 外面碰不到
    private double price;
    private boolean isBorrowed;

    public Book(String title, double price) {
        setTitle(title);
        setPrice(price);
    }
    // getter —— 公开读
    public String getTitle()  { return title; }
    // setter —— 公开写,带校验
    public void setTitle(String title) {
        if (title == null || title.isEmpty())
            throw new IllegalArgumentException("书名不能为空");
        this.title = title;
    }
    public double getPrice()  { return price; }
    public void setPrice(double price) {
        if (price < 0) throw new IllegalArgumentException("价格不能为负");
        this.price = price;
    }
    // boolean 的 getter 习惯用 is 开头
    public boolean isBorrowed() { return isBorrowed; }
    // 业务方法——不一定是简单的 getter/setter
    public void borrow() {
        if (isBorrowed) throw new IllegalStateException("已被借出");
        isBorrowed = true;
    }
    public void returnBook() { isBorrowed = false; }
}

语言:Java 运行b.setPrice(-50) 运行时抛出异常

关键改变

  • 字段全部 private——b.price = -50 编译不通过
  • 提供 public getter/setter——读写经过你的代码,可拒绝非法数据

封装的意义远不止校验

内部可修改字段名、改变存储方式、增加缓存——只要 getter/setter 签名不变,调用方一行不改。

这就是信息隐藏。接口不变,实现随意换。

Java Bean 命名约定

框架(Spring、Jackson)依赖这套规范:

字段类型gettersetter
String namegetName()setName(String)
boolean activeisActive()setActive(boolean)
int countgetCount()setCount(int)

包(Package)——防止撞名

= Java 命名空间。反向域名约定:com.atlas.library.model.Book

java
package com.atlas.library.model;  // 文件第一行
public class Book { ... }

// 使用:
import com.atlas.library.model.Book;

目录结构 = 包名路径:com/atlas/library/model/Book.java

一个正确的 Java Bean

java
package com.atlas.library.model;
public class Book {
    private String title;
    public Book(String title) { this.title = title; }
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
}

差异窗口:C++ 与 Python

C++class 默认 private,struct 默认 public;头文件/实现分离:

cpp
class Book {
private:
    std::string title;
public:
    Book(const std::string& t);
    std::string getTitle() const;
};

Python:没有真 private——靠双下划线名称修饰:

python
class Book:
    def __init__(self, title):
        self.__title = title
    @property
    def title(self):
        return self.__title

下一步

类中的字段属于"每个对象"。那"总共创建了多少本书"这个信息放哪?

下一节:staticch07-static.md

Built with VitePress | Software Systems Atlas