注解、小辣椒实体类全部注解、链式调用注解、IDEA lombok注解下载配置使用、spring boot lombok所有注解

注解、小辣椒实体类全部注解、链式调用注解、IDEA lombok注解下载配置使用、spring boot lombok所有注解

1、idea安装lombok插件

1.下载

  1. 首先我们需要安装IntelliJ IDEA中的lombok插件,打开IntelliJ IDEA后点击菜单栏中的File–>Settings,或者使用快捷键Ctrl+Alt+S进入到设置页面。
    在这里插入图片描述
  2. 我们点击设置中的Plugins进行插件的安装,在右侧选择Browse repositories…,然后在搜索页面输入lombok变可以查询到下方的Lombok Plugin,鼠标点击Lombok Plugin可在右侧看到Install按钮,点击该按钮便可安装。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    3.我们在安装页面可以看到lombok具体支持的所有注解,在安装过程中有Downloading Plugins的提示,安装过程中进度条会变化。需要提醒的是,在安装过程中一定要保证网络连接可用且良好,否则可能会安装失败。安装成功后我们可以看到右侧的Restart按钮,此时可先不操作,因为我们还有后续的配置工作。安装完成后我们再回到Plugins,此时在右侧可以搜索到lombok,而安装前是不行的。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.配置注解处理器

  1. 同样我们在Settings设置页面,我们点击Build,Execution,Deployment–>选择Compiler–>选中Annotation Processors,然后在右侧勾选Enable annotation processing即可。
    在这里插入图片描述
    在这里插入图片描述

lombok插件的使用

  1. 使用前我们需要说明的是安装的插件只是一个调用,就像我们使用maven插件一样,本机需要安装maven才行。我们在使用lombok前也需要添加lombok的依赖。lombok的版本一直在更新,大家可以在百度搜索框输入lombok maven找到最新的依赖版本。
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.18.8</version>
</dependency>
  1. 接下来我们编辑一个实体类Student,添加三个属性,最后在类上添加@Data属性,这个注解可以帮我们在.class文件中生成类中所有属性的get/set方法、equals、canEqual、hashCode、toString方法等。
    在这里插入图片描述
  2. 么编辑完代码后我们如何查看生成的方法呢?在菜单栏点击View–>Tool Windows–>Structure,便可以看到类中所有的方法了,这些都是lombok帮我自动生成的。
    在这里插入图片描述
    在这里插入图片描述

注意事项

  1. 安装lombok插件过程中需要联网,另外安装需要配置Annotation Processors支持。
  2. 如果该经验对您有用的话,请帮忙点赞支持,非常感谢!

注解

注解列表

在这里插入图片描述

案例

1.@AllArgsConstructor——包含所有参数的构造方法

2.@NoArgsConstructor——无参数的构造方法

@NoArgsConstructor的使用方式与@AllArgsConstructor相同

/**
*示例类1
*/
@AllArgsConstructor
public class Demo {
    private String name;		//姓名
    private int age;			//年龄
}
/**
*示例类2
*/
@AllArgsConstructor
class Parent {
    private Integer id;			//ID
}

/*编译后的两个class如下:*/

/**
*示例类1
*/
public class Demo {
    private String name;		//姓名
    private int age;			//年龄

    public Demo(String name, int age) {
        this.name = name;	//姓名
        this.age = age;		//年龄
    }
}

//第二个类
class Parent {
    private Integer id;		//ID

    public Parent(Integer id) {
        this.id = id;	//ID
    }
}

此注解并不会把父类的属性id拿到Demo的构造器里面去,这是需要注意的地方。并且它也没有默认的构造器了

@AllArgsConstructor(access = AccessLevel.PROTECTED, staticName = "test")
public class Demo {
	private final int finalVal = 10;	//最终值
    private String name;		//姓名
    private int age;		//年龄
}

/*编译后class如下:*/

public class Demo {
	private final int finalVal = 10;	//最终值
    private String name;		//姓名
    private int age;		//年龄

    private Demo(String name, int age) {
        this.name = name;
        this.age = age;
    }

    protected static Demo test(String name, int age) {
        return new Demo(name, age);
    }
}

可以指定生成的构造器的访问权限。但是,但是如果指定了一个静态方法,那么构造器会自动会被private,只通过静态方法对外提供反问,并且我们发现final的属性值,是不会放进构造函数里面的。

3.@RequiredArgsConstructor——使类中所有带有@NonNull注解的或者带有final修饰的成员变量生成对应的构造方法

@RequiredArgsConstructor
public class Demo {
    private final int finalVal = 10;	//最终值
    @NonNull
    private String name;		//姓名
    @NonNull
    private int age;		//年龄
}

/*编译后class如下:*/

public class Demo {
    private final int finalVal = 10;	//最终值
    @NonNull
    private String name;		//姓名
    @NonNull
    private int age;		//年龄

    public Demo(@NonNull String name, @NonNull int age) {
        if (name == null) {
            throw new NullPointerException("name is marked @NonNull but is null");
        } else {
            this.name = name;
            this.age = age;
        }
    }
}

解释:该注解会识别@nonNull字段,然后以该字段为元素产生一个构造函数。备注:如果所有字段都没有@nonNull注解,那效果同NoArgsConstructor

4.@Builder——一种比较推崇的构建值对象的方式

非常推荐的一种构建值对象的方式。缺点就是父类的属性不能产于builder

@Builder
public class Demo {
    private final int finalVal = 10;	//最终值
    private String name;		//姓名
    private int age;		//年龄
}

/*编译后class如下:*/

public class Demo {
private final int finalVal = 10;	//最终值
private String name;		//姓名
private int age;		//年龄

Demo(String name, int age) {
    this.name = name;
    this.age = age;
}

public static Demo.DemoBuilder builder() {
    return new Demo.DemoBuilder();
}

public static class DemoBuilder {
    private String name;
    private int age;

    DemoBuilder() {
    }

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

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

    public Demo build() {
        return new Demo(this.name, this.age);
    }

    public String toString() {
        String var10000 = this.name;
        return this.age;
    }
}

这样我们构造一个对象就可以优雅的这么来:

public static void main(String[] args) {
    Demo demo = Demo.builder().name("aa").age(10).build();	//如同链式调用
    System.out.println(demo); 
}

5.@Cleanup——能够自动释放资源

这个注解用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法。如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法,就用输入输出流来

public static void main(String[] args) throws Exception {
	//读取本地文件
   @Cleanup InputStream in = new FileInputStream(args[0]);
   //写入文件
    @Cleanup OutputStream out = new FileOutputStream(args[1]);
    byte[] b = new byte[1024];
    while (true) {
        int r = in.read(b);
        if (r == -1) break;
        out.write(b, 0, r);
    }
}

/*编译后class如下:*/

public static void main(String[] args) throws Exception {
    FileInputStream in = new FileInputStream(args[0]);//读取本地文件
    try {
        FileOutputStream out = new FileOutputStream(args[1]);//写入文件
        try {
            byte[] b = new byte[1024];
            while(true) {
                int r = in.read(b);
                if (r == -1) {
                    return;
                }
                out.write(b, 0, r);
            }
        } finally {
            if (Collections.singletonList(out).get(0) != null) {
                out.close();
            }
        }
    } finally {
        if (Collections.singletonList(in).get(0) != null) {
            in.close();
        }
    }
}

就这么简单的一个注解,就实现了优雅的关流操作哟。

6.@Data——强悍的组合功能包

相当于注解集合。效果等同于 @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor 由于生成的代码篇幅太长,这里就不给demo了,效果同上5个注解的效果,牛掰!!!

需要注意的是,这里不包括@NoArgsConstructor和@AllArgsConstructor

7.@Value——只读性很强的注解

@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。

8.@ToString——toString生成方法

生成toString方法

@ToString
public class Demo {
    private final int finalVal = 10;
    private transient String name = "aa";
    private int age;

}

public static void main(String[] args) throws Exception {
    Demo demo = new Demo();
    System.out.println(demo); //Demo(finalVal=10, age=0)
}

我们发现静态字段它是不输出的。有些关键的属性,可以控制toString的输出,我们可以了解一下

@ToString(
		//是否使用字段名
        includeFieldNames = true,
        //排除某些字段
        exclude = {"name"},
        //只使用某些字段
        of = {"age"},
        //是否让父类字段也参与 默认false
        callSuper = true
)

备注:大多数情况下,使用默认的即可,毕竟大多数情况都是POJO

9.@EqualsAndHashCode——生成equals(Object other)和hashCode()

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;
    }
  }
}

/*编译后class如下:*/

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;
    }
  }
}

10.@Getter

11.@Setter

这一对注解不用说就应该知道是啥意思了吧
用在成员变量上面或者类上面,相当于为成员变量生成对应的get和set方法,同时还可以为生成的方法指定访问修饰符,当然,默认为public这两个注解直接用在类上,可以为此类里的所有非静态成员变量生成对应的get和set方法。如果是final变量,那就只会有get方法

@Getter
@Setter
public class Demo {
    private final int finalVal = 10;	//最终值
    private String name;		//姓名
    private int age;		//年龄
}

/*编译后class如下:*/

public class Demo {
    private final int finalVal = 10;	//最终值
    private String name;		//姓名
    private int age;		//年龄
    
	public Demo() {
	}
	
	public int getFinalVal() {
	    Objects.requireNonNull(this);
	    return 10;
	}
	
	public String getName() {
	    return this.name;
	}
	
	public int getAge() {
	    return this.age;
	}
	
	public void setName(String name) {
	    this.name = name;
	}
	
	public void setAge(int age) {
	    this.age = age;
	}
}

12.@NonNull——产生一个关于此参数的非空检查

这个注解可以用在成员方法或者构造方法的参数前面,会自动产生一个关于此参数的非空检查,如果参数为空,则抛出一个空指针异常。

//成员方法参数加上@NonNull注解
public String getName(@NonNull Person p){
    return p.getName();
}

/*编译后class如下:*/

public String getName(@NonNull Person p){
    if(p==null){
        throw new NullPointerException("person");
    }
    return p.getName();
}

13.@SneakyThrows——将方法中的代码用try-catch语句包裹起来

这个注解用在方法上,可以将方法中的代码用try-catch语句包裹起来,捕获异常并在catch中用Lombok.sneakyThrow(e)把异常抛出,可以使用@SneakyThrows(Exception.class)的形式指定抛出哪种异常

@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
    return new String(bytes, "UTF-8");
}

/*编译后此方法如下:*/

@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
     try{
         return new String(bytes, "UTF-8");
     }catch(UnsupportedEncodingException uee){
         throw Lombok.sneakyThrow(uee);
     }
 }

Lombok.sneakyThrow的代码

 public static RuntimeException sneakyThrow(Throwable t) {
        if (t == null) {
            throw new NullPointerException("t");
        } else {
            return (RuntimeException)sneakyThrow0(t);
        }
    }

    private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
        throw t;
    }

其实就是转化为了RuntimeException

14.@Synchronized——效果和synchronized关键字相同

这个注解用在类方法或者实例方法上,效果和synchronized关键字相同,区别在于锁对象不同,对于类方法和实例方法,synchronized关键字的锁对象分别是类的class对象和this对象,而@Synchronized得锁对象分别是私有静态final对象LOCK和私有final对象lock,当然,也可以自己指定锁对象。

@Synchronized
public static void hello() {
    System.out.println("world");
}

@Synchronized
public int answerToLife() {
    return 42;
}

@Synchronized("readLock")
public void foo() {
    System.out.println("bar");
}

/*编译后方法如下:*/

public static void hello() {
    Object var0 = $LOCK;
    synchronized($LOCK) {
        System.out.println("world");
    }
}

public int answerToLife() {
    Object var1 = this.$lock;
    synchronized(this.$lock) {
        return 42;
    }
}

public void foo() {
    Object var1 = this.readLock;
    synchronized(this.readLock) {
        System.out.println("bar");
    }
}

七个日志注解

15.@CommonsLog

16.@JBossLog

17.@Log

18.@Log4j

19.@Log4j2

20.@Slf4j

21.@XSlf4j

这些个注解用在类上,可以省去从日志工厂生成日志对象这一步,直接进行日志记录,具体注解根据日志工具的不同而不同,同时,可以在注解中使用topic来指定生成log对象时的类名。不同的日志注解总结如下。

@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
@JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
@Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
@Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
@Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
@Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
@XSlf4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

@Slf4j这个注解还是非常有用的

@Slf4j
class Parent {
}

//topic的名称
@Slf4j
@CommonsLog(topic = "commonLog")
class Parent {
}

/*编译后class如下:*/

class Parent {
    private static final Logger log = LoggerFactory.getLogger(Parent.class);
    Parent() {
    }
}

class Parent {
    private static final Logger log = LoggerFactory.getLogger("commonLog");
    Parent() {
    }
}

22.@Accessors——一个为getter和setter设计的更流畅的注解(链式调用)

这个注解要搭配@Getter与@Setter使用,用来修改默认的setter与getter方法的形式。所以单独使用是没有意义的

@Accessors(fluent = true)		//链式调用
@Getter		//get方法
@Setter		//set方法
public class Demo extends Parent {
    private final int finalVal = 10;	//最终值
    private String name;		//姓名
    private int age;		//年龄
}

/*编译后class如下:*/

public class Demo extends Parent {
    private final int finalVal = 10;	//最终值
    private String name;		//姓名
    private int age;		//年龄

    public Demo() {
    }

    public int finalVal() {
        Objects.requireNonNull(this);
        return 10;
    }

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

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

    public Demo name(String name) {		//方法返回的是对象
        this.name = name;
        return this;
    }

    public Demo age(int age) {		//方法返回的是对象
        this.age = age;
        return this;
    }
}

注意:下面两个赋值方法(set)返回的是对象
它的三个参数:

  1. chain 链式的形式 这个特别好用,方法连缀越来越方便了
  2. fluent 流式的形式(若无显示指定chain的值,也会把chain设置为true)
  3. prefix 生成指定前缀的属性的getter与setter方法,并且生成的getter与setter方法时会去除前缀
@Accessors(prefix = "xxx")
@Getter
@Setter
public class Demo extends Parent {
    private final int finalVal = 10;	//最终值
    private String xxxName;		//姓名
    private int age;		//年龄
}

/*编译后class如下:*/

public class Demo extends Parent {
    private final int finalVal = 10;	//最终值
    private String xxxName;		//姓名
    private int age;		//年龄

    public Demo() {
    }

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

    public void setName(String xxxName) {
        this.xxxName = xxxName;
    }
}

我们发现prefix可以在生成get/set的时候,去掉xxx等prefix前缀,达到很好的一致性。但是,但是需要注意,因为此处age没有匹配上xxx前缀,所有根本就不给生成,所以使用的时候一定要注意。属性名没有一个以其中的一个前缀开头,则属性会被lombok完全忽略掉,并且还会产生一个警告。

23.@Delegate——注释的属性,会把这个属性对象的公有非静态方法合到当前类

注意:公共 非静态方法代理模式,把字段的方法代理给类,默认代理所有方法。

public class Demo extends Parent {
    private final int finalVal = 10;	//最终值
    @Delegate
    private String xxxName;		//姓名
    private int age;		//年龄
}

/*编译后class如下:*/

//把String类的公共 非静态方法全拿来了
public class Demo extends Parent {
    private final int finalVal = 10;
    private String xxxName;
    private int age;

    public Demo() {
    }

    public int length() {
        return this.xxxName.length();
    }

    public boolean isEmpty() {
        return this.xxxName.isEmpty();
    }

    public char charAt(int index) {
        return this.xxxName.charAt(index);
    }

    public int codePointAt(int index) {
        return this.xxxName.codePointAt(index);
    }
    ……//等等
}

注意:它不能用于基本数据类型字段比如int,只能用在包装类型比如Integer
参数:

  1. types:指定代理的方法
  2. excludes:和types相反

不常用的注解

24.@Generated——标注源代码中的某些东西是由某些工具生成的

package javax.annotation;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
 * 目的:@Generated标记已生成的源代码,也区分单个文件中用户编写的代码和生成的代码
 * 1. 使用时,必须有代码生成器的名称(完整名)
 * 2. 生成日期必须遵循 ISO 8601标准。例如:2001-07-04T12:08:56.235-0700
 * @author TCM
 * @create 2017年10月16日下午2:06:28
 * @since Common Annotations 1.0
 */
@Documented
@Retention(SOURCE)
@Target({PACKAGE, TYPE, ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD, 
        LOCAL_VARIABLE, PARAMETER})
public @interface Generated {
	
	/**
	 * 代码生成器的名称
	 * 使用完整名,如:com.acme.generator.CodeGen
	 * @return
	 */
	String[] value();
	
	/**
	 * 生成源代码的日期
	 * @return
	 */
	String date() default "";
	
	/**
	 * 代码生成器生成代码包含的注释
	 * @return
	 */
	String comments() default "";
}

25.@Singular——注释类型单数

import lombok.Builder;
import lombok.Singular;
import java.util.Collection;
import java.util.Set;
import java.util.SortedMap;
import com.google.common.collect.ImmutableList;
@Builder
public class SingularExample<T extends Number> {
    private @Singular Set<String> occupations;
    private @Singular("axis") ImmutableList<String> axes;
    private @Singular SortedMap<Integer, T> elves;
    private @Singular Collection<?> minutiae;
}

/*编译后class如下:*/

import java.util.Collection;
import java.util.Set;
import java.util.SortedMap;
import com.google.common.collect.ImmutableList;
public class SingularExample<T extends Number> {
    private Set<String> occupations;
    private ImmutableList<String> axes;
    private SortedMap<Integer, T> elves;
    private Collection<?> minutiae;
    SingularExample(Set<String> occupations, ImmutableList<String> axes, SortedMap<Integer, T> elves, Collection<?> minutiae) {
        this.occupations = occupations;
        this.axes = axes;
        this.elves = elves;
        this.minutiae = minutiae;
    }

    public static class SingularExampleBuilder<T extends Number> {
        private java.util.ArrayList<String> occupations;
        private com.google.common.collect.ImmutableList.Builder<String> axes;
        private java.util.ArrayList<Integer> elves$key;
        private java.util.ArrayList<T> elves$value;
        private java.util.ArrayList<java.lang.Object> minutiae;
        SingularExampleBuilder() {
        }
        public SingularExampleBuilder<T> occupation(String occupation) {
            if (this.occupations == null) {
                this.occupations = new java.util.ArrayList<String>();
            }
            this.occupations.add(occupation);
            return this;
        }

        @java.lang.SuppressWarnings("all")
        public SingularExampleBuilder<T> occupations(java.util.Collection<? extends String> occupations) {
            if (this.occupations == null) {
                this.occupations = new java.util.ArrayList<String>();
            }
            this.occupations.addAll(occupations);
            return this;
        }

        public SingularExampleBuilder<T> axis(String axis) {
            if (this.axes == null) {
                this.axes = com.google.common.collect.ImmutableList.builder();
            }
            this.axes.add(axis);
            return this;
        }

        public SingularExampleBuilder<T> axes(java.lang.Iterable<? extends String> axes) {
            if (this.axes == null) {
                this.axes = com.google.common.collect.ImmutableList.builder();
            }
            this.axes.addAll(axes);
            return this;
        }

        public SingularExampleBuilder<T> elf(Integer elfKey, T elfValue) {
            if (this.elves$key == null) {
                this.elves$key = new java.util.ArrayList<Integer>();
                this.elves$value = new java.util.ArrayList<T>();
            }
            this.elves$key.add(elfKey);
            this.elves$value.add(elfValue);
            return this;
        }

        public SingularExampleBuilder<T> elves(java.util.Map<? extends Integer, ? extends T> elves) {
            if (this.elves$key == null) {
                this.elves$key = new java.util.ArrayList<Integer>();
                this.elves$value = new java.util.ArrayList<T>();
            }
            for (java.util.Map.Entry<? extends Integer, ? extends T> $lombokEntry : elves.entrySet()) {
                this.elves$key.add($lombokEntry.getKey());
                this.elves$value.add($lombokEntry.getValue());
            }
            return this;
        }

        public SingularExampleBuilder<T> minutia(java.lang.Object minutia) {
            if (this.minutiae == null) {
                this.minutiae = new java.util.ArrayList<java.lang.Object>();
            }
            this.minutiae.add(minutia);
            return this;
        }

        public SingularExampleBuilder<T> minutiae(java.util.Collection<?> minutiae) {
            if (this.minutiae == null) {
                this.minutiae = new java.util.ArrayList<java.lang.Object>();
            }
            this.minutiae.addAll(minutiae);
            return this;
        }

        public SingularExample<T> build() {
            java.util.Set<String> occupations;
            switch (this.occupations == null ? 0 : this.occupations.size()) {
                case 0:
                    occupations = java.util.Collections.emptySet();
                    break;
                case 1:
                    occupations = java.util.Collections.singleton(this.occupations.get(0));
                    break;
                default:
                    occupations = new java.util.LinkedHashSet<String>(this.occupations.size() < 1073741824 ? 1 + this.occupations.size() + (this.occupations.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);
                    occupations.addAll(this.occupations);
                    occupations = java.util.Collections.unmodifiableSet(occupations);
            }

            com.google.common.collect.ImmutableList<String> axes = this.axes == null ? com.google.common.collect.ImmutableList.<String>of() : this.axes.build();
            java.util.SortedMap<Integer, T> elves = new java.util.TreeMap<Integer, T>();
            if (this.elves$key != null)
                for (int $i = 0; $i < (this.elves$key == null ? 0 : this.elves$key.size()); $i++)
                    elves.put(this.elves$key.get($i), this.elves$value.get($i));
            elves = java.util.Collections.unmodifiableSortedMap(elves);
            java.util.Collection<java.lang.Object> minutiae;
            switch (this.minutiae == null ? 0 : this.minutiae.size()) {
                case 0:
                    minutiae = java.util.Collections.emptyList();
                    break;
                case 1:
                    minutiae = java.util.Collections.singletonList(this.minutiae.get(0));
                    break;
                default:
                    minutiae = java.util.Collections.unmodifiableList(new java.util.ArrayList<java.lang.Object>(this.minutiae));
            }
            return new SingularExample<T>(occupations, axes, elves, minutiae);
        }
        
        @java.lang.Override
        public java.lang.String toString() {
            return "SingularExample.SingularExampleBuilder(occupations=" + this.occupations + ", axes=" + this.axes + ", elves$key=" + this.elves$key + ", elves$value=" + this.elves$value + ", minutiae=" + this.minutiae + ")";
        }
    }

    @java.lang.SuppressWarnings("all")
    public static <T extends Number> SingularExampleBuilder<T> builder() {
        return new SingularExampleBuilder<T>();
    }
}

26.@Val

27.@Var

为什么不用@Val和@Var?
val可以作为局部变量声明的类型,而不必编写实际类型。val注解将从初始化程序表达式中推断类型。局部变量也将成为最终变量。此功能仅适用于局部变量和foreach循环,不适用于字段(实体类的成员变量)。同时,初始化表达式是必需的。
var和val的差别在于,val修饰的局部变量没有被标记为final。

public class ValVarExample {
    public static void main(String[] args) {

        val name = "cauchy6317";
        var age = Integer.valueOf(12);
        System.out.println(name.getClass());
        System.out.println(age.getClass());
    }
}

/*编译后class如下:*/

public class ValVarExample {
    public ValVarExample() {
    }

    public static void main(String[] args) {
        String name = "cauchy6317";
        Integer age = 12;
        System.out.println("cauchy6317".getClass());
        System.out.println(age.getClass());
    }
}

可以看到,val修饰的name是String类型,var修饰age是Integer类型,然而反编译后的name并没有加上final修饰。但是,如果重新为name赋值,编译会出错。

28.@NonFinal——设置不为Final

@FieldDefaults和@Value也有这功能

29.@SuperBuilder——让子类的builder继承父类builder的行为

Lombok在v1.18.2版本中针对这个问题增加了@SuperBuilder注解,子类和父类中都添加@SuperBuilder注解,子类builder即可继承父类builder。

@SuperBuilder
public class Parent {
    // get,set添加在指定属性上
    @Getter @Setter private int id;
    //如果需要让build出的对象属性使用默认值,需要添加@Builder.Default注解
    @Builder.Default
    @Getter @Setter private String name = "unknown";
}
 
@SuperBuilder
@Data
public class Child extends Parent {
    private String ext;
}

//调用示例
Child c1 = Child.builder().id(1).name("名称").ext("子类属性ext").build();
System.out.println(c1.getId());

注意: 关于builder的继承,Lombok Plugin尚未更新支持@SuperBuilder,所以以上写法在IDE下还会提示编译错误,等更新吧

30.@UtilityClass——工具类注解

@UtilityClass
public class Utility {
    public String getName() {
        return "name";
    }
}
public static void main(String[] args) {
    // Utility utility = new Utility(); 构造函数为私有的,
    System.out.println(Utility.getName());
 
}

31.@Wither—— 该注解放在属性前面,会生成属性的withXXX方法,可以使用withAge(xxx).withXX() 链式操作

import lombok.AccessLevel;
import lombok.NonNull;
import lombok.With;
public class WithExample {
  @With(AccessLevel.PROTECTED) @NonNull private final String name;
  @With private final int age;
  public WithExample(String name, int age) {
    if (name == null) throw new NullPointerException();
    this.name = name;
    this.age = age;
  }
}

/*编译后class如下:*/
import lombok.NonNull;
public class WithExample {
  private @NonNull final String name;
  private final int age;
  public WithExample(String name, int age) {
    if (name == null) throw new NullPointerException();
    this.name = name;
    this.age = age;
  }
  protected WithExample withName(@NonNull String name) {
    if (name == null) throw new java.lang.NullPointerException("name");
    return this.name == name ? this : new WithExample(name, age);
  }
  public WithExample withAge(int age) {
    return this.age == age ? this : new WithExample(name, age);
  }
}

在过程中可能出现的问题

1.@Builder和@NoArgsConstructor一起使用时

建议去掉@NoArgsConstructor添加@AllArgsConstructor

2.@builder注解影响设置默认值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值