一、前言
在Java面向对象的开发中,通过Class定义类,类中包括字段(属性)、方法、构造函数等。在由类创建具体实例时,通过类中属性的get(设置器)和set(访问器)设置或者访问类中的属性。使用过程中,我们都清楚如何使用属性,但是1、属性的访问修饰符为什么设置成private;2、为什么要使用get和set方法;3、lombok库的注解的使用和区别。通过上述问题的详细介绍来学习关于类属性的使用。
二、类的get与set方法
在面向对象的特性中有继承、封装、多态性,封装是保护类创建对象的数据和行为,将其隐藏在类的内部,并提供公共的方法来访问成员变量和成员函数,从而确保数据的安全访问,防止数据被任意修改。在Java中通过修饰符(private、public、protected)来实现封装,类的属性属于成员变量,类外部的其它对象访问类内属性必须提供一种安全的访问方式,所以通过创建set或者get方法来访问属性。
/**
*
*/
public class Student {
/**
* id
*/
private Long id;
public Long getId(){
return id;
}
public void setId(long id) {
this.id = id;
}
/**
* 姓名
*/
private String name;
public String getName() {
return name;
}
public void setName(String name){
this.name = name;
}
/**
* 年龄
*/
private Integer age;
public Integer getAge(){
return age;
}
private void setAge(){
this.age = age;
}
/**
* 出生年月
*/
private LocalDate birthday;
public LocalDate getBirthday() {
return birthday;
}
public void setBirthday(LocalDate birthday) {
this.birthday = birthday;
}
/**
* 地址
*/
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address){
this.address = address;
}
}
上述定义Student类,类中定义值类型或者引用类型的属性(id、name、age、address)并且设置访问修饰符private,在没有设置相应的访问器时,外部创建Student实例无法访问其属性,达到内部细节的隐藏和封装性,要访问该属性如上设置每一个属性的get和set方法。
在使用get和set方法,我们通过①不设置get方法或者不设置set方法或者定义其访问修饰符来限制权限;②在set方法中写入相关验证规则、条件等进行判断,阻止非法的值设置;③在类中一些属性是其它属性的附属属性,则在该属性中的get方法中通过其它属性计算来获取,关闭设置方法。
package com.example.demo;
import com.sun.deploy.util.StringUtils;
import java.time.LocalDate;
import java.time.Period;
/**
*
*/
public class Student {
/**
* id
*/
private Long id;
public Long getId(){
return id;
}
public void setId(long id) {
this.id = id;
}
/**
* 姓名
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) throws Exception {
if(name.isEmpty()){
throw new Exception("姓名错误!");
}
this.name = name;
}
/**
* 年龄
*/
private Integer age;
public Integer getAge(){
LocalDate birthDate = LocalDate.of(1990, 1, 1);
Period period = birthDate.until(this.birthday);
return period.getYears();
}
/**
* 出生年月
*/
private LocalDate birthday;
public LocalDate getBirthday() {
return birthday;
}
public void setBirthday(LocalDate birthday) {
this.birthday = birthday;
}
/**
* 地址
*/
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address){
this.address = address;
}
}
三、lombok库的使用
在Student例子中,get和set方法的访问修饰符、方法名称、方法体差异都不大,所以通过引入lombok类库来简化相关操作,如下引入依赖项。
在lombok库中包含相关注解,通过该注解快速实现类的构造器、访问方法get和设置方法set,如@Data、@Builder、@NoArgsConstructor、@AllArgsConstructor、@getter、@setter、Accessors(chain=true)、@Value等。
@Data:@Data是一个复合注解(@Setter、@Getter、@ToString、@EqualsAndHashCode、@NoArgsConstructor),使用在类中,会生成默认的无参构造函数、所有属性的getter、所有非 final 属性的 setter 方法、并且重写 toString、equals、hashcode 方法(单独使用@Data注解,是会生成无参数构造方法)。
@Builder:@Builder是比较推荐构建值对象的方式,该描述符表明其将类改造成Builder(建造者)的设计模式,构建类的实例,用在类、方法或者构造函数上(单独使用@Builder注解,是会生成了全属性的构造方法)。
@Value:@Value注解和@Data类似,区别在于会把类的全部成员变量的访问修饰符定义成private final,并且不会生成set()方法。
@NoArgsConstructor:@NoArgsConstructor是会提供无参的构造函数。
@AllArgsConstructor:@AllArgsConstructor是会提供全参数的构造函数,默认public修饰符,要修改修饰符使用(access = AccessLevel.PROTECTED)属性设置。
@RequiredArgsConstructor:@RequiredArgsConstructor是会提供构造函数(带参数或不带参数),带参数则参数必须是以 final 修饰的未经初始化的字段或者是以 @NonNull 注解的未经初始化的字段,还可以使用staticName选项生成指定名称的static方法,返回一个调用相应的构造方法产生的对象。
@setter:@setter会生成相应的set设置方法,要修改修饰符使用(access = AccessLevel.PROTECTED)属性设置。
@getter:@getter会生成相应的get访问方法。
@Accessors(chain=true):Accessors(chain=true)是为类的setter方法提供链式调用,@Accessors(chain=true) 是将生成的 setter() 方法返回 this ,而 @Builder 是再对象内部创建一个构建器,通过这个构建器来最终创建对象。
注意:@Builder 注解会给类默认生成全参构造,这样就没有了默认的无参构造,在Spring这类容器中默认调用无参构造就报错了,所以要加上@NoArgsConstructor 和 @AllArgsConstructor 注解。