平时遇到遇到有关Java的文章,尤其是Spring Boot的文章,总是可以看到POJO、JavaBean。这都是啥!啥!啥啥啥!!!
今天咱们就一劳永逸,弄清楚这都是 啥!啥!啥!
Plain Old Java Obejects
POJO是Palin Old Java Objects的缩写。字面意思——普通老式的Java对象(一头雾水)?
当我们谈论一个POJO类时,我们所描述的是一个直接的类型,没有对任何特定框架的引用。一个POJO类对我们的属性和方法没有命名规则。
我们创建一个EmployeePojo,它拥有3个属性。看这个类可以应用于任何Java程序中,没有绑定任何框架。
import java.time.LocalDate;
public class EmployeePojo {
public String firstName;
public String lastName;
private final LocalDate startDate;
public EmployeePojo(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
public String name() {
return this.firstName + " " + this.lastName;
}
public LocalDate getStart() {
return this.startDate;
}
}
但是我们在构建、访问和修改这个类的状态时并没有真正的 遵循任何真正的惯例。缺乏惯例会导致两个问题:
- 增加了试图了解如何使用它的程序员的学习曲线。
- 限制了框架的能力更倾向于惯例而非配置,理解如何使用这个类,并且增强其能力。
我们接下来就第二点展开讨论。
反射一个POJO类
-
首先引入commons-beanutils,依赖
<dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.4</version> </dependency> -
然后检查EmployeePojo类的属性
import org.apache.commons.beanutils.PropertyUtils; import java.beans.PropertyDescriptor; public class ReflectionExample { public static void main(String[] args) { System.out.println("Fields for EmployeePojo are:"); for (PropertyDescriptor pd : PropertyUtils.getPropertyDescriptors(EmployeePojo.class)) { System.out.println("EmployeePojo property: " + pd.getDisplayName()); } } } 执行结果如下,仅打印出 start,另外两个属性并没有显示出来。理想状态下,我们希望看到的是:irstName, lastName, 和 startDate.
Fields for EmployeePojo are: EmployeePojo property: start这个问题怎么解决呢?好消息是,许多Java库默认支持一种叫做JavaBean的命名规则。
JavaBeans
JavaBean是POJO的子集,JavaBean围绕着我们如何实现他引入了很多严格的规则。
- 访问级别——属性是私有的,可以暴露getters和setters
- 方法命名——以getX和setX命名
- 默认构造器——必须提供一个没有参数的构造方法
- 可序列化的(Serializable )—— 实现可序列化的接口允许我们存储状态
使用JavaBean改造EmployeePojo
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDate;
@Data //为了是代码更简洁,使用lombok.Data注释代替getX和setX方法。
public class EmployeeBean implements Serializable {
private static final long serialVersionUID = -3760445487636086034L;
private String firstName;
private String lastName;
private LocalDate startDate;
public EmployeeBean() {
}
public EmployeeBean(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
}
接下来改造一下ReflectionExample
import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyDescriptor;
public class ReflectionExample {
public static void main(String[] args) {
System.out.println("Fields for EmployeeBean are:");
for (PropertyDescriptor pd : PropertyUtils.getPropertyDescriptors(EmployeeBean.class)) {
System.out.println("EmployeePojo property: " + pd.getDisplayName());
}
}
}
执行结果如下
Fields for EmployeeBean are:
EmployeePojo property: firstName
EmployeePojo property: lastName
EmployeePojo property: startDate
JavaBean的缺点
JavaBean的引入虽然可以解决一些问题,但企业有3点潜在的缺点不容忽视
- 可变性--由于我们的JavaBeans的setter方法是可变的,这可能导致并发性或一致性问题。
- 模板--我们必须为所有的属性引入获取器,为大多数属性引入设置器,这其中的大部分可能是不必要的。
- 零参数构造器--我们经常需要在构造器中设置参数,以确保对象在有效状态下被实例化,但JavaBean标准要求我们提供一个零参数构造器。
看完这期文章,你还会对POJO、JavaBean等概念不明所以吗?欢迎前来讨论~~~
\