什么是 set 和 get 方法?
set 和 get 方法,通常被称为 访问器方法 或 存取器方法。

get方法 (Getter):用于获取(读取)一个对象的私有成员变量的值。set方法 (Setter):用于设置(修改)一个对象的私有成员变量的值。
它们遵循一种特定的命名规范,这使得代码非常易于阅读和理解。
为什么需要 set 和 get 方法?(核心思想)
直接问这个问题:为什么我们不直接把成员变量设为 public,然后直接在外部访问和修改它们呢?
为什么不这样做:
// 不推荐的做法
public class Person {
public String name; // 公开的成员变量
public int age; // 公开的成员变量
}
这样做有几个致命的缺点:

- 数据无保障:任何人都可以随意修改你的变量,而无需经过任何检查,你可以把年龄设置为负数:
person.age = -100,这在逻辑上是错误的。 - 代码脆弱:如果业务逻辑发生变化,比如所有年龄计算都需要以“周岁”为准,但你之前已经把变量直接暴露出去了,那么所有直接使用这个变量的地方都需要修改,工作量巨大且容易出错。
- 无法添加额外逻辑:你可能希望在设置年龄时,打印一条日志;或者在获取名字时,进行一些格式化处理,如果变量是
public的,你无法在这些操作发生时插入逻辑。
set 和 get 方法就是为了解决以上问题而生的。
核心优势:
- 封装:这是面向对象三大特性(封装、继承、多态)之一,通过将成员变量设为
private(私有),我们将其“隐藏”在类内部,只通过public(公有)的set和get方法来提供受控的访问。 - 数据保护:你可以在
set方法中加入验证逻辑,确保只有合法的值才能被赋给变量。 - 灵活性:你可以在不改变外部接口(
set和get方法的签名)的情况下,随意修改类的内部实现,你可以把String name改为String firstName和String lastName,但只要getName()和setName()方法的行为保持一致,外部代码就无需改动。 - 附加行为:可以在
set或get方法中添加日志、触发事件、计算派生值等。
set 和 get 方法的命名规范
Java 社区有非常严格的命名规范,遵循这些规范能让你的代码更专业、更易读。
-
Getter 方法:
(图片来源网络,侵删)- 方法名以
get开头。 - 后面紧跟成员变量的首字母大写形式。
- 返回类型:与成员变量的类型相同。
- 参数:无。
// 成员变量 private String name; // Getter public String getName() { return this.name; } - 方法名以
-
Setter 方法:
- 方法名以
set开头。 - 后面紧跟成员变量的首字母大写形式。
- 返回类型:
void。 - 参数:一个参数,类型与成员变量相同。
// 成员变量 private int age; // Setter public void setAge(int age) { this.age = age; } - 方法名以
特例:布尔类型的 Getter
对于 boolean 类型的成员变量,Getter 方法有一个更简洁的命名方式:
- 标准方式:
isXxx() - 也可以使用
getXxx(),但isXxx()更常用、更符合直觉。
// 成员变量
private boolean isActive;
// Getter (推荐)
public boolean isActive() {
return this.isActive;
}
// Getter (也可以,但不常用)
public boolean getActive() {
return this.isActive;
}
// Setter (和普通类型一样)
public void setActive(boolean active) {
this.isActive = active;
}
一个完整的示例
下面是一个完整的 Student 类,展示了如何正确地使用 private 成员变量和 public 的 set/get 方法,并在其中加入了数据验证逻辑。
public class Student {
// 1. 将成员变量设为 private,实现封装
private String studentId;
private String name;
private int age;
private double score;
// 2. 构造方法 (可选,但推荐)
public Student(String studentId, String name, int age, double score) {
this.studentId = studentId;
this.setName(name); // 使用 setter 方法来复用验证逻辑
this.setAge(age); // 使用 setter 方法来复用验证逻辑
this.setScore(score);
}
// 3. Getter 和 Setter 方法
// Getter for studentId
public String getStudentId() {
return studentId;
}
// Setter for studentId (假设ID一旦创建不能修改)
public void setStudentId(String studentId) {
this.studentId = studentId;
}
// Getter for name
public String getName() {
return name;
}
// Setter for name (带验证逻辑)
public void setName(String name) {
if (name == null || name.trim().isEmpty()) {
System.out.println("错误:姓名不能为空!");
// 可以选择抛出异常或者设置一个默认值
// this.name = "未知";
return;
}
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age (带验证逻辑)
public void setAge(int age) {
if (age < 0 || age > 120) {
System.out.println("错误:年龄必须在 0 到 120 之间!");
return;
}
this.age = age;
}
// Getter for score
public double getScore() {
return score;
}
// Setter for score (带验证逻辑)
public void setScore(double score) {
if (score < 0 || score > 100) {
System.out.println("错误:分数必须在 0 到 100 之间!");
return;
}
this.score = score;
}
// 一个普通方法,用于展示学生信息
public void displayInfo() {
System.out.println("学生信息:");
System.out.println(" 学号: " + this.getStudentId());
System.out.println(" 姓名: " + this.getName());
System.out.println(" 年龄: " + this.getAge());
System.out.println(" 分数: " + this.getScore());
}
}
如何使用这个类:
public class Main {
public static void main(String[] args) {
// 创建一个合法的学生对象
Student student1 = new Student("S001", "张三", 20, 95.5);
student1.displayInfo();
System.out.println("--------------------");
// 尝试修改学生信息,使用 setter 方法
student1.setAge(21);
student1.setScore(88.0);
student1.displayInfo();
System.out.println("--------------------");
// 尝试设置非法数据,setter 方法会进行拦截
student1.setAge(-5); // 会打印错误信息
student1.setScore(150); // 会打印错误信息
student1.setName(""); // 会打印错误信息
// 数据没有被修改
student1.displayInfo();
}
}
输出结果:
学生信息:
学号: S001
姓名: 张三
年龄: 20
分数: 95.5
--------------------
学生信息:
学号: S001
姓名: 张三
年龄: 21
分数: 88.0
--------------------
错误:年龄必须在 0 到 120 之间!
错误:分数必须在 0 到 100 之间!
错误:姓名不能为空!
学生信息:
学号: S001
姓名: 张三
年龄: 21
分数: 88.0
现代 Java 中的 set 和 get:Lombok
虽然手动编写 set 和 get 方法是理解其原理的最佳方式,但在实际开发中,一个类往往有很多成员变量,手动编写这些重复的代码会非常繁琐。
为了解决这个问题,像 Lombok 这样的库应运而生,Lombok 通过注解,可以在编译时自动为你的类生成 setter、getter、toString()、equals()、hashCode() 等样板代码。
使用 Lombok,上面的 Student 类可以简化为:
import lombok.Getter;
import lombok.Setter;
@Getter // 为所有 private 成员变量生成 getter
@Setter // 为所有 private 成员变量生成 setter
public class StudentLombok {
private String studentId;
private String name;
private int age;
private double score;
// 构造方法
public StudentLombok(String studentId, String name, int age, double score) {
this.studentId = studentId;
this.name = name;
this.age = age;
this.score = score;
}
// 你仍然可以手动定义某个 setter 来加入特殊逻辑
@Setter
public void setAge(int age) {
if (age < 0 || age > 120) {
System.out.println("错误:年龄必须在 0 到 120 之间!");
return;
}
this.age = age;
}
// ... 其他方法
}
注意:使用 Lombok 需要在你的 IDE(如 IntelliJ IDEA 或 Eclipse)中安装插件,并在项目中添加 Lombok 的依赖。
| 特性 | 描述 |
|---|---|
| 目的 | 实现封装,保护对象内部数据,提供受控的访问方式。 |
| 命名 | getXxx() / setXxx(),布尔类型可用 isXxx()。 |
| 关键字 | 成员变量为 private,set/get 方法为 public。 |
| 核心优势 | 数据验证:确保数据合法性。 灵活性:内部实现可变,外部接口不变。 安全性:防止非法访问和修改。 附加行为:可在访问时添加日志、计算等逻辑。 |
| 现代实践 | 手动编写以学习原理,在实际项目中使用 Lombok 等工具提高效率。 |
掌握 set 和 get 方法是迈向专业 Java 开发者的第一步,它体现了面向对象设计的精髓。
