Java中的封装是面向对象编程的三大特性之一,核心思想是将类的内部实现细节隐藏起来,只对外暴露必要的访问接口,通过封装控制属性访问可以避免外部代码随意修改类的内部状态,保证数据的安全性和一致性。
封装控制属性访问的核心逻辑
封装控制属性访问的本质是通过访问修饰符限制属性的可见范围,再提供统一的方法让外部获取或修改属性值,所有对属性的操作都经过预设的逻辑校验,避免非法数据的产生。
访问修饰符的选择
Java提供了四种访问修饰符,控制属性访问时最常用的修饰符是private,它的作用是将属性的访问范围限制在当前类内部,外部类无法直接访问该属性。不同访问修饰符的访问范围对比如下:
| 修饰符 | 当前类 | 同包类 | 子类 | 其他包类 |
|---|---|---|---|---|
| private | 可访问 | 不可访问 | 不可访问 | 不可访问 |
| default(默认) | 可访问 | 可访问 | 不可访问 | 不可访问 |
| protected | 可访问 | 可访问 | 可访问 | 不可访问 |
| public | 可访问 | 可访问 | 可访问 | 可访问 |
如果希望完全控制属性的访问,优先选择private修饰属性,这是封装的基础。
getter和setter方法的编写
将属性设置为private之后,外部无法直接访问,此时需要提供getter方法用于获取属性值,setter方法用于修改属性值。这两个方法通常是public修饰的,方便外部调用。
下面以用户类为例,演示封装属性的实现:
public class User {
// 用private修饰属性,外部无法直接访问
private String name;
private int age;
// getter方法,用于获取name属性值
public String getName() {
return name;
}
// setter方法,用于修改name属性值,可添加校验逻辑
public void setName(String name) {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("姓名不能为空");
}
this.name = name;
}
// getter方法,用于获取age属性值
public int getAge() {
return age;
}
// setter方法,用于修改age属性值,添加年龄合法性校验
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄必须在0到150之间");
}
this.age = age;
}
}
上述代码中,name和age属性都被private修饰,外部无法直接通过user.name的方式访问。如果外部需要修改年龄,必须调用setAge方法,方法内部会校验年龄是否合法,避免设置无效的年龄值。
封装控制属性访问的常见技巧
只读属性的实现
如果某个属性只允许外部获取,不允许修改,可以只提供getter方法,不提供setter方法。比如用户的身份证号,创建之后不应该被修改:
public class User {
private String idCard;
// 构造方法初始化身份证号
public User(String idCard) {
this.idCard = idCard;
}
// 只提供getter方法,不提供setter方法,实现只读属性
public String getIdCard() {
return idCard;
}
}
只写属性的实现
如果某个属性只允许外部设置,不允许直接获取,可以只提供setter方法,不提供getter方法,比如用户的密码属性,通常不需要对外暴露获取方法:
public class User {
private String password;
// 只提供setter方法,不提供getter方法,实现只写属性
public void setPassword(String password) {
if (password == null || password.length() < 6) {
throw new IllegalArgumentException("密码长度不能小于6位");
}
this.password = password;
}
// 密码校验方法,不直接返回密码
public boolean checkPassword(String inputPassword) {
return this.password.equals(inputPassword);
}
}
访问修饰符的灵活使用
如果属性需要被同包类或者子类访问,但不想被其他包的类访问,可以使用protected或者默认修饰符,不过这种情况需要谨慎使用,避免破坏封装的完整性。通常建议优先使用private修饰属性,再根据需要开放访问接口。
封装控制属性访问的注意事项
首先,不要在getter和setter方法中添加过于复杂的业务逻辑,否则会导致方法的职责不清晰,后续维护困难。其次,如果属性是引用类型,getter方法返回时需要注意是否需要返回副本,避免外部修改引用对象影响内部状态。比如属性是一个List集合:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Order {
private List<String> items;
public Order() {
this.items = new ArrayList<>();
}
// 返回不可修改的集合副本,避免外部修改内部集合
public List<String> getItems() {
return Collections.unmodifiableList(new ArrayList<>(items));
}
public void addItem(String item) {
if (item == null || item.trim().isEmpty()) {
return;
}
items.add(item);
}
}
这种情况下如果直接返回items的引用,外部调用者修改返回的List会直接影响Order内部的items属性,破坏封装的保护作用。通过返回副本或者不可修改的集合,可以避免这个问题。
封装控制属性访问是Java开发中非常基础的实践,规范的封装可以让代码结构更清晰,减少不必要的bug,在开发过程中应该养成合理使用封装的习惯,从类的设计阶段就考虑属性的访问控制规则。
Java封装访问控制privategetter_setter修改时间:2026-06-10 11:27:38