刚从git拉取的工程,发现idea报错,找不到bean中的的get、set方法。是因为类中使用了lombok的注解@Data,idea本身是不理解这个注解的,会报错找不到set方法,所以需要在idea中安装插件lombok plugin。

Lombok 是一款 Java 开发插件,使得 Java 开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的 Java 模型对象(POJO)。在开发环境中使用 Lombok 插件后,Java 开发人员可以节省出重复构建,诸如 hashCode 和 equals 这样的方法以及各种业务对象模型的 accessor 和 toString 等方法的大量时间。对于这些方法,Lombok 能够在编译源代码期间自动帮我们生成这些方法,但并不会像反射那样降低程序的性能。

 

Lombok安装

IDEA中安装lombok插件

打开IDEA的Setting –> 选择Plugins选项 –> 选择MarketPlace –> 搜索lombok –> 点击安装 –> 安装完成重启IDEA –> 安装成功

getResourcePackageName 找不到资源 找不到get方法_ide

引入依赖  pom.xml中加入

<dependencies>
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.6</version>
		<scope>provided</scope>
	</dependency>
</dependencies>

Lombok的scope=provided,说明它只在编译阶段生效,不需要打入包中。事实正是如此,Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件。

 

 

@Getter/@Setter

该注解使用在类或者属性上,为字段生成GetterSetter方法。

  • 注解在类上会为类中的所有非静态成员变量生成GetterSetter方法
  • 非boolean类型和boolean类型:都生成getXxxxxsetXxxx,可以用is+大写开头的Boolean类型
  • 如果类和字段上均使用相同的注解,字段上的注解会覆盖相同的注解,以字段上的注解为准
  • 手工编写的Getter和Setter方法会抑制lombok中相同名称的Getter和Setter方法的生成。
  • 可以通过AccessLevel.NONE禁用某个字段上的@Setter、@Getter
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class GetterSetterExample {
  private int age = 10;
  @Getter(AccessLevel.NONE)@Setter(AccessLevel.PROTECTED) private String name;
}
public class GetterSetterExample {

  private int age = 10;
  private String name;
  //自动生成Getter、Setter
  public int getAge() {
    return age;
  } 
  public void setAge(int age) {
    this.age = age;
  }

  //属性优先级高于类
  protected void setName(String name) {
    this.name = name;
  }
}

@ToString

生成toString()方法,默认情况下,它会以逗号分隔,按顺序,打印类名称以及每个非静态成员变量。

  • 如果需要可以通过注释参数includeFieldNames来控制输出中是否包含的属性名称。
  • 通过@ToString.Exclude注解某一字段,可以从生成的方法中排除特定字段。
  • 也可使用@ToString(onlyExplicitlyIncluded = true)标注类,然后使用@ToString.Include标注想要输入的字段。
  • 通过@ToString(callSuper = true)参数继承父类的输出。
import lombok.ToString;

@ToString
public class ToStringExample {
  private static final int STATIC_VAR = 10;
  private String name;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  @ToString.Exclude private int id;
  
  public String getName() {
    return this.name;
  }
   //继承父类,排除属性名
  @ToString(callSuper=true, includeFieldNames=false)
  public static class Square extends Shape {
    private final int width, height;
    
    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }
}
public class ToStringExample {
    private static final int STATIC_VAR = 10;
    private String name;
    private Shape shape = new Square(5, 10);
    private String[] tags;
    private int id;

    public String getName() {
        return this.name;
    }

    private static class Square extends Shape {
        private final int width;
        private final int height;

        private Square(int width, int height) {
            this.width = width;
            this.height = height;
        }

        @Override
        public java.lang.String toString() {
            //继承父类,排除属性名
            return "ToStringExample.Square(super=" + super.toString() + ", " + this.width + ", " + this.height + ")";
        }
    }

    @Override
    public java.lang.String toString() {
        //exclude "id"
        return "ToStringExample(name=" + this.getName() + ", shape=" + this.shape + ", tags=" + java.util.Arrays.deepToString(this.tags) + ")";
    }
}

@EqualsAndHashCode

任何类使用@EqualsAndHashCode标注生成hashCode()和equals()方法,默认情况下,它将使用所有非静态,非transient字段。但可以通过在可选的@EqualsAndHashCode.Include 或者@EqualsAndHashCode.Exclude注解字段来排除或包含指定字段

类似于@toString

  • @EqualsAndHashCode.Exclude排除具体字段
  • @EqualsAndHashCode.Include包含指定字段,需和属性onlyExplicitlyIncluded = true配合使用
  • 通过callSuper = true继承父类。
import lombok.EqualsAndHashCode;

@EqualsAndHashCode
public class EqualsAndHashCodeExample {
  private transient int transientVar = 10;
  private String name;
  private double score;
  @EqualsAndHashCode.Exclude private Shape shape = new Square(5, 10);
  private String[] tags;
  @EqualsAndHashCode.Exclude private int id;
  
  public String getName() {
    return this.name;
  }
  
  @EqualsAndHashCode(callSuper=true)
  public static class Square extends Shape {
    private final int width, height;
    
    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }
}
import java.util.Arrays;

public class EqualsAndHashCodeExample {
  private transient int transientVar = 10;
  private String name;
  private double score;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;
  
  public String getName() {
    return this.name;
  }
  
  @Override public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof EqualsAndHashCodeExample)) return false;
    EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
    if (!other.canEqual((Object)this)) return false;
    if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
    if (Double.compare(this.score, other.score) != 0) return false;
    if (!Arrays.deepEquals(this.tags, other.tags)) return false;
    return true;
  }
  
  @Override public int hashCode() {
    final int PRIME = 59;
    int result = 1;
    final long temp1 = Double.doubleToLongBits(this.score);
    result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
    result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
    result = (result*PRIME) + Arrays.deepHashCode(this.tags);
    return result;
  }
  
  protected boolean canEqual(Object other) {
    return other instanceof EqualsAndHashCodeExample;
  }
  
  public static class Square extends Shape {
    private final int width, height;
    
    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }
    
    @Override public boolean equals(Object o) {
      if (o == this) return true;
      if (!(o instanceof Square)) return false;
      Square other = (Square) o;
      if (!other.canEqual((Object)this)) return false;
      if (!super.equals(o)) return false;
      if (this.width != other.width) return false;
      if (this.height != other.height) return false;
      return true;
    }
    
    @Override public int hashCode() {
      final int PRIME = 59;
      int result = 1;
      result = (result*PRIME) + super.hashCode();
      result = (result*PRIME) + this.width;
      result = (result*PRIME) + this.height;
      return result;
    }
    
    protected boolean canEqual(Object other) {
      return other instanceof Square;
    }
  }
}

@Accessors

@Accessors 主要用于控制生成的getter和setter

  • fluent
  • chain
  • prefix

 

@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor

给类增加无参构造器、指定参数的构造器、包含所有参数的构造器

  • @NoArgsConstructor:使用在类上,提供一个无参构造器。当类中有final字段没有被初始化时,编译器会报错,此时可用@NoArgsConstructor(force = true),然后就会为没有初始化的final字段设置默认值 0 / false / null, 这样编译器就不会报错。对于具有约束的字段(例如@NonNull字段),不会生成检查或分配,因此请注意,正确初始化这些字段之前,这些约束无效。
  • @RequiredArgsConstructor:使用在类上,生成一个有参构造函数,其中每个参数对应为类中所有带有 @NonNull 注解的和以final修饰的未经初始化的字段。
  • @RequiredArgsConstructor(staticName = “of”)会生成一个of()的静态工厂方法,并把构造方法设置为私有的。
  • @AllArgsConstructor:使用在类上,该注解提供一个全参数的构造方法,默认不提供无参构造。 这里的全参不包括已初始化的final字段。
  • 这三个注解都会忽略static变量。
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.NonNull;

@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ConstructorExample<T> {
    private int x, y;
    private final String name;
    @NonNull
    private T description;
    private static int count;
    @NoArgsConstructor
    public static class NoArgsExample {
        @NonNull
        private String field;
    }
}
// Generated by delombok at Mon Feb 25 09:40:52 CST 2019
package com.zybank.lombokdemo.entity;

import lombok.*;

public class ConstructorExample<T> {
    private int x;
    private int y;
    private final String name;
    @NonNull
    private T description;
    private static int count;


    public static class NoArgsExample {
        @NonNull
        private String field;

        @java.lang.SuppressWarnings("all")
        public NoArgsExample() {
        }
    }

    private ConstructorExample(final String name, @NonNull final T description) {
        if (description == null) {
            throw new java.lang.NullPointerException("description is marked @NonNull but is null");
        }
        this.name = name;
        this.description = description;
    }

    public static <T> ConstructorExample<T> of(final String name, @NonNull final T description) {
        return new ConstructorExample<T>(name, description);
    }

    protected ConstructorExample(final int x, final int y, final String name, @NonNull final T description) {
        if (description == null) {
            throw new java.lang.NullPointerException("description is marked @NonNull but is null");
        }
        this.x = x;
        this.y = y;
        this.name = name;
        this.description = description;
    }
}

@Data

@Data 包含了 @ToString@EqualsAndHashCode@Getter /@Setter@RequiredArgsConstructor的功能。

  • 虽然@Data注解非常有用,但是它的控制粒度较粗(Class级别),而且@Data不能设置callSuper、includeFieldNames 和exclude等,如果需要改变默认值,可以使用相应的注解,@Data会自动遵循这些注解。
  • @Data提供了一个可以生成静态工厂的单一参数@Data(staticConstructor=”of”),会生成一个of()的静态工厂方法,并把构造方法设置为私有的。
package com.zybank.lombokdemo;

import lombok.*;
@ToString(includeFieldNames=false)
//生成静态工厂
@Data(staticConstructor = "of")
public class DataExample {
    private final String name;
    //自定义Setter方法
    @Setter(AccessLevel.PACKAGE)
    private int age;
    private double score;
    private String[] tags;
}
// Generated by delombok at Mon Feb 25 16:27:59 CST 2019
package com.zybank.lombokdemo;

import lombok.*;

public class DataExample {
    private final String name;
    private int age;
    private double score;
    private String[] tags;

    @java.lang.Override
    public java.lang.String toString() {
        return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + java.util.Arrays.deepToString(this.getTags()) + ")";
    }

    private DataExample(final String name) {
        this.name = name;
    }

    public static DataExample of(final String name) {
        return new DataExample(name);
    }

    public String getName() {
        return this.name;
    }

    public int getAge() {
        return this.age;
    }

    @java.lang.SuppressWarnings("all")
    public double getScore() {
        return this.score;
    }

    public String[] getTags() {
        return this.tags;
    }

    public void setScore(final double score) {
        this.score = score;
    }
    
    void setAge(final int age) {
        this.age = age;
    }
   
    public void setTags(final String[] tags) {
        this.tags = tags;
    }
   

    @java.lang.Override
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (!(o instanceof DataExample)) return false;
        final DataExample other = (DataExample) o;
        if (!other.canEqual((java.lang.Object) this)) return false;
        final java.lang.Object this$name = this.getName();
        final java.lang.Object other$name = other.getName();
        if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
        if (this.getAge() != other.getAge()) return false;
        if (java.lang.Double.compare(this.getScore(), other.getScore()) != 0) return false;
        if (!java.util.Arrays.deepEquals(this.getTags(), other.getTags())) return false;
        return true;
    }

    protected boolean canEqual(final java.lang.Object other) {
        return other instanceof DataExample;
    }

    @java.lang.Override
    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final java.lang.Object $name = this.getName();
        result = result * PRIME + ($name == null ? 43 : $name.hashCode());
        result = result * PRIME + this.getAge();
        final long $score = java.lang.Double.doubleToLongBits(this.getScore());
        result = result * PRIME + (int) ($score >>> 32 ^ $score);
        result = result * PRIME + java.util.Arrays.deepHashCode(this.getTags());
        return result;
    }
}

@Value

该注解用于修饰类,是@Data的不可变形式,生成immutable Class。字段都被修饰为privatefinal,默认的情况下不会生成settter,默认类本身也是final的。
实际上@Value等价于final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter

import lombok.AccessLevel;
import lombok.experimental.NonFinal;
import lombok.experimental.Wither;
import lombok.ToString;
import lombok.Value;

@Value public class ValueExample {
  String name;
  @Wither(AccessLevel.PACKAGE) @NonFinal int age;
  double score;
  protected String[] tags;
  
  @ToString(includeFieldNames=true)
  @Value(staticConstructor="of")
  public static class Exercise<T> {
    String name;
    T value;
  }
}
import java.util.Arrays;

public final class ValueExample {
  private final String name;
  private int age;
  private final double score;
  protected final String[] tags;
  
  @java.beans.ConstructorProperties({"name", "age", "score", "tags"})
  public ValueExample(String name, int age, double score, String[] tags) {
    this.name = name;
    this.age = age;
    this.score = score;
    this.tags = tags;
  }
  
  public String getName() {
    return this.name;
  }
  
  public int getAge() {
    return this.age;
  }
  
  public double getScore() {
    return this.score;
  }
  
  public String[] getTags() {
    return this.tags;
  }
  
  @java.lang.Override
  public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof ValueExample)) return false;
    final ValueExample other = (ValueExample)o;
    final Object this$name = this.getName();
    final Object other$name = other.getName();
    if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
    if (this.getAge() != other.getAge()) return false;
    if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
    if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
    return true;
  }
  
  @java.lang.Override
  public int hashCode() {
    final int PRIME = 59;
    int result = 1;
    final Object $name = this.getName();
    result = result * PRIME + ($name == null ? 43 : $name.hashCode());
    result = result * PRIME + this.getAge();
    final long $score = Double.doubleToLongBits(this.getScore());
    result = result * PRIME + (int)($score >>> 32 ^ $score);
    result = result * PRIME + Arrays.deepHashCode(this.getTags());
    return result;
  }
  
  @java.lang.Override
  public String toString() {
    return "ValueExample(name=" + getName() + ", age=" + getAge() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")";
  }
  
  ValueExample withAge(int age) {
    return this.age == age ? this : new ValueExample(name, age, score, tags);
  }
  
  public static final class Exercise<T> {
    private final String name;
    private final T value;
    
    private Exercise(String name, T value) {
      this.name = name;
      this.value = value;
    }
    
    public static <T> Exercise<T> of(String name, T value) {
      return new Exercise<T>(name, value);
    }
    
    public String getName() {
      return this.name;
    }
    
    public T getValue() {
      return this.value;
    }
    
    @java.lang.Override
    public boolean equals(Object o) {
      if (o == this) return true;
      if (!(o instanceof ValueExample.Exercise)) return false;
      final Exercise<?> other = (Exercise<?>)o;
      final Object this$name = this.getName();
      final Object other$name = other.getName();
      if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
      final Object this$value = this.getValue();
      final Object other$value = other.getValue();
      if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;
      return true;
    }
    
    @java.lang.Override
    public int hashCode() {
      final int PRIME = 59;
      int result = 1;
      final Object $name = this.getName();
      result = result * PRIME + ($name == null ? 43 : $name.hashCode());
      final Object $value = this.getValue();
      result = result * PRIME + ($value == null ? 43 : $value.hashCode());
      return result;
    }
    
    @java.lang.Override
    public String toString() {
      return "ValueExample.Exercise(name=" + getName() + ", value=" + getValue() + ")";
    }
  }
}

@NonNull

使用@NonNull注解标注方法或构造函数的参数,让lombok为您生成null-check语句。

配合lomok中其他生成完整方法和构造函数的注解(比如@Setter注解),仅需将@NonNull标注在成员变量上,就可在生成的方法和构造函数中加入null-check。反之,就必须在入参中标注。

lombok会探测开发者自己编写的null-check语句,如果存在就不在生成。if条件语句必须严格按照PARAMNAME == null的形式书写。

import lombok.NonNull;

public class NonNullExample {
    private String name;

    public void setName(@NonNull String name) {
        this.name = name;
    }
}
public class NonNullExample {
    private String name;

    public void setName(String name) {
        if (name == null) {
            throw new NullPointerException("name is marked @NonNull but is null");
        }
        this.name = name;
    }
}

 

 

@Builder : 注解在类上, 为类提供一个内部的 Builder

@Synchronized : 注解在方法上, 为方法提供同步锁

@Log4j : 注解在类上, 为类提供一个属性名为 log 的 log4j 的日志对象

@Slf4j : 注解在类上, 为类提供一个属性名为 log 的 log4j 的日志对象