Java Bean 规范详解
1. 什么是 Java Bean?
Java Bean 是一种符合特定规范的 Java 类,主要用于封装多个对象作为一个单独的对象(即对象)。它是一个可重用的软件组件,具有以下特点:
- 可序列化:实现
Serializable
接口 - 无参构造函数:提供公共的无参构造方法
- 私有字段:属性使用私有访问修饰符
- 公共getter/setter:通过公共方法访问私有属性
2. 核心规范
2.1 基本要求
import java.io.Serializable;
public class User implements Serializable {
// 私有字段
private String name;
private int age;
private boolean active;
// 1. 必须有无参构造函数
public User() {
}
// 2. 属性的getter方法
public String getName() {
return name;
}
// 3. 属性的setter方法
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 4. boolean类型的getter方法可以是isXXX()
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
2.2 命名规范
属性类型 | Getter 方法命名 | Setter 方法命名 |
---|---|---|
String name |
getName() |
setName(String name) |
boolean active |
isActive() 或 getActive() |
setActive(boolean active) |
int age |
getAge() |
setAge(int age) |
3. 属性类型处理
3.1 基本数据类型
public class Product implements Serializable {
private long id;
private double price;
private int quantity;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
3.2 布尔类型特殊处理
public class Account implements Serializable {
private boolean enabled;
private boolean verified;
// 推荐使用 isXXX() 命名
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
// 也可以使用 getXXX() 命名
public boolean getVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
}
3.3 数组和集合类型
import java.util.List;
import java.util.ArrayList;
public class Order implements Serializable {
private String[] tags;
private List<OrderItem> items;
public Order() {
items = new ArrayList<>();
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public List<OrderItem> getItems() {
return items;
}
public void setItems(List<OrderItem> items) {
this.items = items;
}
}
4. 高级特性
4.1 只读和只写属性
public class ReadOnlyBean implements Serializable {
private String readOnlyProperty;
private String writeOnlyProperty;
// 只读属性:只有getter,没有setter
public String getReadOnlyProperty() {
return readOnlyProperty;
}
// 只写属性:只有setter,没有getter(不常见)
public void setWriteOnlyProperty(String value) {
this.writeOnlyProperty = value;
}
}
4.2 索引属性
public class IndexedBean implements Serializable {
private String[] data;
public String[] getData() {
return data;
}
public void setData(String[] data) {
this.data = data;
}
// 索引属性访问方法
public String getData(int index) {
return data[index];
}
public void setData(int index, String value) {
this.data[index] = value;
}
}
5. 事件处理(可选)
Java Bean 支持事件监听机制:
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class ObservableBean implements Serializable {
private String value;
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public String getValue() {
return value;
}
public void setValue(String newValue) {
String oldValue = this.value;
this.value = newValue;
// 触发属性变更事件
pcs.firePropertyChange("value", oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}
6. BeanInfo 类(可选)
可以创建自定义的 BeanInfo 类来控制 Bean 在 IDE 中的显示:
import java.beans.BeanInfo;
import java.beans.SimpleBeanInfo;
import java.beans.PropertyDescriptor;
import java.beans.IntrospectionException;
public class UserBeanInfo extends SimpleBeanInfo {
@Override
public PropertyDescriptor[] getPropertyDescriptors() {
try {
PropertyDescriptor name = new PropertyDescriptor("name", User.class);
PropertyDescriptor age = new PropertyDescriptor("age", User.class);
PropertyDescriptor active = new PropertyDescriptor("active", User.class);
// 设置属性显示名称等元数据
name.setDisplayName("用户姓名");
age.setDisplayName("用户年龄");
active.setDisplayName("是否激活");
return new PropertyDescriptor[] {name, age, active};
} catch (IntrospectionException e) {
throw new RuntimeException(e);
}
}
}
7. 使用场景和最佳实践
7.1 常见使用场景
- GUI 开发:Swing 组件
- 持久化框架:Hibernate、MyBatis
- Spring Framework:依赖注入
- JSON 序列化:Jackson、Gson
- JSP EL 表达式
7.2 最佳实践
public class BestPracticeBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
// 1. 总是提供无参构造函数
public BestPracticeBean() {
}
// 2. 可以提供有参构造函数,但不能替代无参构造函数
public BestPracticeBean(String name, int age) {
this.name = name;
this.age = age;
}
// 3. Getter/Setter 方法应该简单
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
// 可以添加简单的验证逻辑
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
this.age = age;
}
// 4. 重写 toString() 方法
@Override
public String toString() {
return "BestPracticeBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
// 5. 重写 equals() 和 hashCode() 方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BestPracticeBean that = (BestPracticeBean) o;
if (age != that.age) return false;
return name != null ? name.equals(that.name) : that.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
8. 与现代框架的结合
8.1 与 Lombok 结合
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserWithLombok implements Serializable {
private String name;
private int age;
private boolean active;
// Lombok 会自动生成:
// - 无参构造函数 (@NoArgsConstructor)
// - 全参构造函数 (@AllArgsConstructor)
// - 所有字段的 getter/setter
// - equals()、hashCode()、toString()
}
8.2 与 Spring Boot 结合
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app.database")
public class DatabaseConfig {
private String url;
private String username;
private String password;
private int poolSize;
// Spring Boot 会自动注入配置值
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public int getPoolSize() { return poolSize; }
public void setPoolSize(int poolSize) { this.poolSize = poolSize; }
}
总结
Java Bean 规范虽然简单,但在 Java 生态系统中扮演着重要角色。理解并遵循这些规范可以:
- 提高代码的可读性和一致性
- 确保与各种框架和工具的兼容性
- 促进团队协作和代码维护
- 支持反射和自省机制
在实际开发中,可以根据具体需求选择是否严格遵循所有规范,但核心的 getter/setter 模式和无参构造函数建议始终遵守。