【小家Java】Lombok的使用详解(最详尽的解释,覆盖讲解所有可用注解),解决@Builder.Default默认值问题(中)

简介: 【小家Java】Lombok的使用详解(最详尽的解释,覆盖讲解所有可用注解),解决@Builder.Default默认值问题(中)

@ToString/@EqualsAndHashCode


这两个注解也比较好理解,就是生成toString,equals和hashcode方法,同时后者还会生成一个canEqual方法,用于判断某个对象是否是当前类的实例。,生成方法时只会使用类中的非静态成员变量,这些都比较好理解。毕竟静态的东西并不属于对象本身


@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"}, //只使用某些字段
        callSuper = true //是否让父类字段也参与 默认false
)


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


@Generated:暂时貌似没什么用

@Getter/@Setter

这一对注解从名字上就很好理解,用在成员变量上面或者类上面,相当于为成员变量生成对应的get和set方法,同时还可以为生成的方法指定访问修饰符,当然,默认为public


这两个注解直接用在类上,可以为此类里的所有非静态成员变量生成对应的get和set方法。如果是final变量,那就只会有get方法


@Getter
@Setter
public class Demo {
    private final int finalVal = 10;
    private String name;
    private int age;
}


编译后:


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


@NonNull


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


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

编译后:

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

@Singular 默认值 暂时也没太大用处


@SneakyThrows


这个注解用在方法上,可以将方法中的代码用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,其实我想说,这个注解也没大用。毕竟我们碰到异常,是希望自己处理的


@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");
        }
    }


我只能说,这个注解也挺鸡肋的。

@Val 很强的类型推断 var注解,在Java10之后就不能使用了


class Parent {
    //private static final val set = new HashSet<String>(); //编译不通过
    public static void main(String[] args) {
        val set = new HashSet<String>();
        set.add("aa");
        System.out.println(set); //[aa]
    }
}

编译后:


class Parent {
    Parent() {
    }
    public static void main(String[] args) {
        HashSet<String> set = new HashSet();
        set.add("aa");
        System.out.println(set);
    }
}


这个和Java10里的Var很像,强大的类型推断。并且不能使用在全局变量上,只能使用在局部变量的定义中。


@Log、CommonsLog、Slf4j、XSlf4j、Log4j、Log4j2等日志注解


这个注解用在类上,可以省去从日志工厂生成日志对象这一步,直接进行日志记录,具体注解根据日志工具的不同而不同,同时,可以在注解中使用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 {
}


编译后:


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


也可topic的名称:

@Slf4j
@CommonsLog(topic = "commonLog")
class Parent {
}


lombok中有experimental的包:

实验性因为:


1.我们可能想将这些特性和更完全的性质支持概念融为一体(普通话:这些性能还在研究)


2.新特性-需要社区反馈


@Accessors 一个为getter和setter设计的更流畅的注解


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


@Accessors(fluent = true)
@Getter
@Setter
public class Demo extends Parent {
    private final int finalVal = 10;
    private String name;
    private int age;
}

编译后

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


它的三个参数解释:


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


编译后:


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完全忽略掉,并且会产生一个警告。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1月前
|
存储 Java C语言
Java代码解释Flash原理
Java代码解释Flash原理
32 0
|
1月前
|
Java Spring 容器
【Java】Spring如何扫描自定义的注解?
【Java】Spring如何扫描自定义的注解?
35 0
|
26天前
|
Java 数据库连接
hibernate注解实体类(Dept.java)
hibernate注解实体类(Dept.java)
13 1
|
26天前
|
Java 数据库连接
Hibernate中使用Criteria查询及注解——(Dept.java)
Hibernate中使用Criteria查询及注解——(Dept.java)
14 1
|
21天前
|
存储 SQL Java
【Java技术指南】「JPA编程专题」让你不再对JPA技术中的“持久化型注解”感到陌生了(二)
【Java技术指南】「JPA编程专题」让你不再对JPA技术中的“持久化型注解”感到陌生了
42 1
|
22天前
|
IDE 安全 Java
Lombok的优缺点不建议使用
Lombok的优缺点不建议使用
18 0
|
26天前
|
Java 数据库连接
hibernate注解实体类(Emp.java)
hibernate注解实体类(Emp.java)
14 1
|
26天前
|
Java 数据库连接
Hibernate中使用Criteria查询及注解——(DeptTest.java)
Hibernate中使用Criteria查询及注解——(DeptTest.java)
8 1
|
26天前
|
Java 数据库连接
Hibernate中使用Criteria查询及注解——(Emp.java)
Hibernate中使用Criteria查询及注解——(Emp.java)
9 0
|
30天前
|
Java
java 自定义注解 实现限流
java 自定义注解 实现限流
10 1