元数据卡
- 前置知识:第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编译不通过 - 提供
publicgetter/setter——读写经过你的代码,可拒绝非法数据
封装的意义远不止校验
内部可修改字段名、改变存储方式、增加缓存——只要 getter/setter 签名不变,调用方一行不改。
这就是信息隐藏。接口不变,实现随意换。
Java Bean 命名约定
框架(Spring、Jackson)依赖这套规范:
| 字段类型 | getter | setter |
|---|---|---|
String name | getName() | setName(String) |
boolean active | isActive() | setActive(boolean) |
int count | getCount() | 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下一步
类中的字段属于"每个对象"。那"总共创建了多少本书"这个信息放哪?
下一节:static → ch07-static.md