什么是 get 和 set 方法?
get 和 set 方法通常被称为 访问器(Accessor) 和 修改器,它们是一种特殊的公共方法,用于获取和修改一个类的私有字段的值。

核心思想: 将类的字段(成员变量)设置为 private(私有),然后通过 public(公共)的 get 和 set 方法来间接地访问和修改这些字段,这种设计模式被称为 封装。
为什么需要 get 和 set 方法?(封装的好处)
直接暴露类的字段(将字段设为 public)被认为是不好的编程实践,因为它会破坏封装性,使用 get 和 set 方法主要有以下几个关键好处:
a) 数据保护
你可以通过 set 方法来控制对私有字段的修改,你可以添加逻辑来防止无效的值被赋给字段。
例子:

public class Person {
private int age; // 年龄不能是负数
// set 方法可以加入验证逻辑
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("年龄不能为负数!");
}
}
// get 方法用于安全地获取值
public int getAge() {
return this.age;
}
}
age 是 public 的,任何人都可以将其设为负数,但通过 setAge 方法,我们可以轻松地阻止这种情况。
b) 灵活性
将来如果需求发生变化,你只需要修改 get 或 set 方法的内部实现,而所有调用这些方法的代码都不需要改变。
例子: 假设你决定存储年龄时,不仅要存数字,还要存一个时间戳,记录年龄是何时设置的。
public class Person {
private int age;
private long lastUpdatedTimestamp;
// 修改 set 方法,增加新功能
public void setAge(int age) {
if (age >= 0) {
this.age = age;
this.lastUpdatedTimestamp = System.currentTimeMillis(); // 新增逻辑
} else {
System.out.println("年龄不能为负数!");
}
}
// 可以新增一个 get 方法来获取时间戳
public long getLastUpdatedTimestamp() {
return this.lastUpdatedTimestamp;
}
// getAge 方法保持不变
public int getAge() {
return this.age;
}
}
所有调用 person.setAge(25) 的地方都无需修改,但它们现在享受到了记录时间戳的新功能。

c) 便于调试和日志记录
你可以在 get 和 set 方法中轻松地添加日志或断点,来跟踪哪些代码在何时访问或修改了你的数据。
例子:
public void setAge(int age) {
System.out.println("尝试设置年龄为: " + age); // 调试日志
if (age >= 0) {
this.age = age;
} else {
System.out.println("年龄不能为负数!");
}
}
d) 延迟计算
get 方法可以不直接返回一个存储的值,而是动态计算并返回。
例子:
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
// get 方法用于计算面积,而不是存储它
public double getArea() {
System.out.println("正在计算面积..."); // 日志
return Math.PI * radius * radius;
}
}
get 和 set 方法的命名约定
在 Java 中,有非常明确的命名约定来遵循:
-
set方法:- 方法名以
set开头。 - 后面紧跟字段名的首字母大写形式,这个过程称为 PascalCase 或 驼峰命名法。
- 有且仅有一个参数,参数类型与字段类型相同,参数名通常与字段名相同。
- 返回类型为
void。
格式:
public void setFieldName(fieldType fieldName) { ... } - 方法名以
-
get方法:- 方法名以
get开头。 - 后面紧跟字段名的首字母大写形式。
- 没有参数。
- 返回类型与字段类型相同。
格式:
public fieldType getFieldName() { ... } - 方法名以
布尔类型的特例:
对于布尔类型的字段(boolean),get 方法的命名有一个常见的替代方案,可以读起来更像一个自然的问题。
- 标准命名:
public boolean isAlive() { ... } - 也可以使用:
public boolean getAlive() { ... }(虽然不常见,但语法正确)
推荐使用 is 前缀,因为它更符合英语习惯。
代码示例
下面是一个完整的、遵循上述约定的 Student 类示例。
// Student.java
public class Student {
// 1. 将字段设为 private,实现数据隐藏
private String name;
private int age;
private boolean isGraduated;
// 2. 提供一个公共的构造器来初始化对象
public Student(String name, int age) {
this.name = name;
this.age = age;
this.isGraduated = false; // 默认值
}
// ====== Getter 方法 ======
// 用于获取私有字段的值
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public boolean isGraduated() { // 布尔类型使用 is 前缀
return this.isGraduated;
}
// ====== Setter 方法 ======
// 用于修改私有字段的值
public void setName(String name) {
// 可以在这里添加验证逻辑,name 不能为 null 或空字符串
if (name != null && !name.trim().isEmpty()) {
this.name = name;
} else {
System.out.println("姓名不能为空!");
}
}
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
System.out.println("年龄必须大于 0!");
}
}
public void setGraduated(boolean graduated) {
isGraduated = graduated;
}
}
如何使用这个类:
// Main.java
public class Main {
public static void main(String[] args) {
// 创建一个 Student 对象
Student student1 = new Student("张三", 20);
// 使用 get 方法获取值
System.out.println("学生姓名: " + student1.getName()); // 输出: 学生姓名: 张三
System.out.println("学生年龄: " + student1.getAge()); // 输出: 学生年龄: 20
System.out.println("是否毕业: " + student1.isGraduated()); // 输出: 是否毕业: false
// 使用 set 方法修改值
student1.setAge(21);
System.out.println("修改后的年龄: " + student1.getAge()); // 输出: 修改后的年龄: 21
// 尝试设置一个无效的年龄
student1.setAge(-5); // 输出: 年龄必须大于 0!
System.out.println("年龄仍然是: " + student1.getAge()); // 输出: 年龄仍然是: 21
// 尝试设置一个无效的姓名
student1.setName(""); // 输出: 姓名不能为空!
System.out.println("姓名仍然是: " + student1.getName()); // 输出: 姓名仍然是: 张三
}
}
现代 Java 的简化:Lombok
手动为每个字段编写 get 和 set 方法(以及 toString, equals, hashCode 等)会非常繁琐且容易出错,为了解决这个问题,社区和工具库提供了很多简化方案,其中最流行的是 Lombok。
Lombok 通过注解在编译时自动为你生成这些样板代码。
使用 Lombok 的 Student 类:
import lombok.Getter;
import lombok.Setter;
@Getter // 为所有 private 字段生成 get 方法
@Setter // 为所有 private 字段生成 set 方法
public class Student {
private String name;
private int age;
private boolean isGraduated;
public Student(String name, int age) {
this.name = name;
this.age = age;
this.isGraduated = false;
}
}
或者,你可以更精确地控制:
import lombok.Getter;
import lombok.Setter;
public class Student {
@Getter // 只为 name 生成 get 方法
private String name;
@Setter @Getter // 为 age 生成 set 和 get 方法
private int age;
@Getter // 只为 isGraduated 生成 get 方法 (会命名为 isGraduated)
private boolean isGraduated;
// ... 构造器 ...
}
使用 Lombok 后,你的 Main 类调用方式完全不变,但代码量大大减少,可读性更高,Lombok 已经成为现代 Java 项目中非常常见的工具。
| 特性 | 描述 |
|---|---|
| 目的 | 实现 封装,是面向对象编程的四大特性之一。 |
| 核心 | 将字段设为 private,通过 public 的 get/set 方法访问。 |
| 好处 | 数据保护、灵活性、便于调试、支持延迟计算。 |
| 命名 | setFieldName(fieldType field),getFieldName(),布尔类型可用 isFieldName()。 |
| 现代实践 | 使用 Lombok 等工具自动生成 get/set 方法,减少样板代码,提高开发效率。 |
掌握 get 和 set 方法是理解 Java 面向对象编程的基石,它不仅是一种语法,更是一种重要的设计思想。
