Lombok使用心得

2018/10/11 Java

Java开发神器,真香

Java业务开发的时候,有很多业务模型,于是就延伸了一堆Getter/Setter,构造方法,ToString等等,如果你不用面向对象,全申明public,当然另当别论。

这里有个神器,lombok,用后,真香。

lombok

Intellij安装

Preferences——Lombok,不赘述了,Lombok在编译过程中生效,不安装撸码的时候极有可能提示你方法找不到。

在pom增加依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.8</version>
</dependency>

Lombok常用注解使用方法

@NonNull (注解能够为方法或构造函数的参数提供非空检查)

public void notNullExample(@NonNull String string) {
    //方法内的代码
}

//=>上面代码相当于如下:

public void notNullExample(String string) {
    if (string != null) {
        //方法内的代码相当于如下:
    } else {
        throw new NullPointerException("null");
    }
}

@Getter/@Setter 注解可以针对类的属性字段自动生成Get/Set方法

public class OrderCreateDemoReq{

    @Getter
    @Setter
    private String customerId;

    @Setter
    @Getter
    private String poolId;
    
    //其他代码……
}

//上面请求Req类的代码相当于如下:

public class OrderCreateDemoReq{
    private String customerId;    
    private String poolId;

    public String getCustomerId(){
         return customerId;
    }

    public String getPoolId(){
         return poolId;
    }

    public void setCustomerId(String customerId){
         this.customerId = customerId;
    }

    public void setPoolId(String poolId){
         this.pool = pool;
    }

}

@ToString 注解,为使用该注解的类生成一个toString方法,默认的toString格式为:ClassName(fieldName= fieleValue ,fieldName1=fieleValue)

@ToString(callSuper=true,exclude="someExcludedField")
public   class Demo extends Bar {

    private boolean someBoolean = true;
    private String someStringField;
    private float someExcludedField;

}

//上面代码相当于如下:

public   class Demo extends Bar {

    private boolean someBoolean = true;
    private String someStringField;
    private float someExcludedField;
   
    @ Override
    public String toString() {
        return "Foo(super=" +   super.toString() +
            ", someBoolean=" +   someBoolean +
            ", someStringField=" +   someStringField + ")";
    }
}

@EqualsAndHashCode注解,为使用该注解的类自动生成equals和hashCode方法

@EqualsAndHashCode(exclude = {"id"}, callSuper =true)
public class LombokDemo extends Demo{
    private int id;
    private String name;
    private String gender;
}

//上面代码相当于如下:

public class LombokDemo extends Demo{

    private int id;
    private String name;
    private String gender;
    
    @Override
    public boolean equals(final Object o) {
        if (o == this) return true;
        if (o == null) return false;
        if (o.getClass() != this.getClass()) return false;
        if (!super.equals(o)) return false;
        final LombokDemo other = (LombokDemo)o;
        if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false;
        if (this.gender == null ? other.gender != null : !this.gender.equals(other.gender)) return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = result * PRIME + super.hashCode();
        result = result * PRIME + (this.name == null ? 0 : this.name.hashCode());
        result = result * PRIME + (this.gender == null ? 0 : this.gender.hashCode());
        return result;
    }

}

@NoArgsConstructor,@RequiredArgsConstructor, @AllArgsConstructor,这几个注解分别为类自动生成了无参构造器、指定参数的构造器和包含所有参数的构造器

@RequiredArgsConstructor(staticName = "of") 
@AllArgsConstructor(access = AccessLevel.PROTECTED) 
public class ConstructorExample<T> { 

  private int x, y; 
  @NonNull private T description; 
  
  @NoArgsConstructor 
  public static class NoArgsExample { 
    @NonNull private String field; 
  } 

}

//上面代码相当于如下:
@RequiredArgsConstructor(staticName = "of") 
@AllArgsConstructor(access = AccessLevel.PROTECTED) 
public class ConstructorExample<T> { 

  private int x, y; 
  @NonNull private T description; 

  @NoArgsConstructor 
  public static class NoArgsExample { 
    @NonNull private String field; 
  } 

}

public class ConstructorExample<T> { 
  private int x, y; 
  @NonNull private T description; 

  private ConstructorExample(T description) { 
    if (description == null) throw new NullPointerException("description"); 
    this.description = description; 
  } 

  public static <T> ConstructorExample<T> of(T description) { 
    return new ConstructorExample<T>(description); 
  } 

  @java.beans.ConstructorProperties({"x", "y", "description"}) 
  protected ConstructorExample(int x, int y, T description) { 
    if (description == null) throw new NullPointerException("description"); 
    this.x = x; 
    this.y = y; 
    this.description = description; 
  } 
  
  public static class NoArgsExample { 
    @NonNull private String field;
    
    public NoArgsExample() { 
    } 
  } 
}

@Data注解作用比较全,其包含注解的集合@ToString,@EqualsAndHashCode,所有字段的@Getter和所有非final字段的@Setter, @RequiredArgsConstructor。其示例代码可以参考上面几个注解的组合

@Builder注解提供了一种比较推崇的构建值对象的方式

@Builder 
public class BuilderExample { 

  private String name; 
  private int age; 

  @Singular private Set<String> occupations; 

}

//上面代码相当于如下:

public class BuilderExample { 

  private String name; 
  private int age; 
  private Set<String> occupations; 

  BuilderExample(String name, int age, Set<String> occupations) { 
    this.name = name; 
    this.age = age; 
    this.occupations = occupations; 
  } 

  public static BuilderExampleBuilder builder() { 
    return new BuilderExampleBuilder(); 
  } 

  public static class BuilderExampleBuilder { 

    private String name; 
    private int age; 
    private java.util.ArrayList<String> occupations;    

    BuilderExampleBuilder() { 
    } 

    public BuilderExampleBuilder name(String name) { 
      this.name = name; 
      return this; 
    } 

    public BuilderExampleBuilder age(int age) { 
      this.age = age; 
      return this; 
    } 

    public BuilderExampleBuilder occupation(String occupation) { 
      if (this.occupations == null) { 
        this.occupations = new java.util.ArrayList<String>(); 
      } 
      this.occupations.add(occupation); 
      return this; 
    } 

    public BuilderExampleBuilder occupations(Collection<? extends String> occupations) { 
      if (this.occupations == null) { 
        this.occupations = new java.util.ArrayList<String>(); 
      } 
      this.occupations.addAll(occupations); 
      return this; 
    } 

    public BuilderExampleBuilder clearOccupations() { 
      if (this.occupations != null) { 
        this.occupations.clear(); 
      }
      return this; 
    } 

    public BuilderExample build() {  
      Set<String> occupations = new HashSet<>(); 
      return new BuilderExample(name, age, occupations); 
    } 

    @verride 
    public String toString() { 
      return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")"; 
    } 
  } 
}

如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候,与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构建器也比JavaBeans更加安全。

// 调用示例
BuilderExample example = new BuilderExample.Builder().setName("test").setAge(20).build();
感兴趣看这里

Lombok是在编译时期生效,再生成class之前把相应代码注入。

img

使用Annotation Processing自定义注解是在编译阶段进行修改,而JDK的反射技术是在运行时动态修改,两者相比,反射虽然更加灵活一些但是带来的性能损耗更加大。

程序员DD

Search

    Table of Contents