User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Java   ›   Java Notes   ›   正文
Java Notes

lombok基本注解

2020-07-07 00:29:11
1377  0 0
参考目录 隐藏
1) 首先,用到的几个注解:
2) @EqualsAndHashCode()注解详解
3) @Accessors注解3个属性说明
4) Lombok 所有注解如下:
5) val示例
6) @NonNull示例
7) @Cleanup示例
8) @Getter/@Setter示例
9) @ToString示例
10) @EqualsAndHashCode示例
11) @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor示例
12) @Data示例
13) @Value示例
14) @Builder示例
15) @SneakyThrows示例
16) @Synchronized示例
17) @Getter(lazy = true)

阅读完需:约 11 分钟

lombok是一款在java开发中简洁化代码十分有用的插件工具。

使用lombok注解,目的和作用就在于不用再去写经常反复去写的(如Getter,Setter,Constructor等)一些代码了。

首先,用到的几个注解:

  1. @Data
    使用这个注解,就不用再去手Getter,Setter,equals,canEqual,hasCode,toString等方法了,注解后在编译时会自动加进去。
  2. @AllArgsConstructor
    使用后添加一个构造函数,该构造函数含有所有已声明字段属性参数
  3. @NoArgsConstructor|
    使用后创建一个无参构造函数
  4. @Builder
    关于Builder较为复杂一些,Builder的作用之一是为了解决在某个类有很多构造函数的情况,也省去写很多构造函数的麻烦,在设计模式中的思想是:用一个内部类去实例化一个对象,避免一个类出现过多构造函数,

首先,建立一个简单的类,并用lombok进行注解:注意这是注解前的代码,可以与后面贴出的注解生成的代码进行比较

@Data //生成getter,setter等函数
@AllArgsConstructor //生成全参数构造函数
@NoArgsConstructor//生成无参构造函数
@Builder
public class test1 {
    String name;
    String age;
    String sex;
}

测试:

public static void main(String[] args) {
 //使用@Builder注解后,可以直接通过Builder设置字段参数
        test1 t1=new test1.test1Builder()
                .name("wang")
                .age("12")
                .sex("man")
                .build();

        System.out.println("name is"+t1.getName()+'\n'+"age is :"+t1.getAge());

    }

通过查看编译后的类,比较注解前后的代码量,发现会省去了很多代码的书写:

public class test1 {
    String name;
    String age;
    String sex;

    public static test1.test1Builder builder() {
        return new test1.test1Builder();
    }

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

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

    public String getSex() {
        return this.sex;
    }

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

    public void setAge(String age) {
        this.age = age;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof test1)) {
            return false;
        } else {
            test1 other = (test1)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$name = this.getName();
                    Object other$name = other.getName();
                    if (this$name == null) {
                        if (other$name == null) {
                            break label47;
                        }
                    } else if (this$name.equals(other$name)) {
                        break label47;
                    }

                    return false;
                }

                Object this$age = this.getAge();
                Object other$age = other.getAge();
                if (this$age == null) {
                    if (other$age != null) {
                        return false;
                    }
                } else if (!this$age.equals(other$age)) {
                    return false;
                }

                Object this$sex = this.getSex();
                Object other$sex = other.getSex();
                if (this$sex == null) {
                    if (other$sex != null) {
                        return false;
                    }
                } else if (!this$sex.equals(other$sex)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof test1;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $name = this.getName();
        int result = result * 59 + ($name == null ? 43 : $name.hashCode());
        Object $age = this.getAge();
        result = result * 59 + ($age == null ? 43 : $age.hashCode());
        Object $sex = this.getSex();
        result = result * 59 + ($sex == null ? 43 : $sex.hashCode());
        return result;
    }

    public String toString() {
        return "test1(name=" + this.getName() + ", age=" + this.getAge() + ", sex=" + this.getSex() + ")";
    }

    @ConstructorProperties({"name", "age", "sex"})
    public test1(String name, String age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public test1() {
    }

    public static class test1Builder {
        private String name;
        private String age;
        private String sex;

        test1Builder() {
        }

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

        public test1.test1Builder age(String age) {
            this.age = age;
            return this;
        }

        public test1.test1Builder sex(String sex) {
            this.sex = sex;
            return this;
        }

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

        public String toString() {
            return "test1.test1Builder(name=" + this.name + ", age=" + this.age + ", sex=" + this.sex + ")";
        }
    }
}

@EqualsAndHashCode()注解详解

原文中提到的大致有以下几点:

1. 此注解会生成equals(Object other) 和 hashCode()方法。

2. 它默认使用非静态,非瞬态的属性

3. 可通过参数exclude排除一些属性

4. 可通过参数of指定仅使用哪些属性

5. 它默认仅使用该类中定义的属性且不调用父类的方法

6. 可通过callSuper=true解决上一点问题。让其生成的方法中调用父类的方法。

另:@Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集。

通过官方文档,可以得知,当使用@Data注解时,则有了@EqualsAndHashCode注解,那么就会在此类中存在equals(Object other) 和 hashCode()方法,且不会使用父类的属性,这就导致了可能的问题。

比如,有多个类有相同的部分属性,把它们定义到父类中,恰好id(数据库主键)也在父类中,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other) 和 hashCode()方法判定为相等,从而导致出错。

修复此问题的方法很简单:

1. 使用@Getter @Setter @ToString代替@Data并且自定义equals(Object other) 和 hashCode()方法,比如有些类只需要判断主键id是否相等即足矣。

2. 或者使用在使用@Data时同时加上@EqualsAndHashCode(callSuper=true)注解。

@Accessors注解3个属性说明

Accessors翻译是存取器。通过该注解可以控制getter和setter方法的形式。

@Accessors(fluent = true)

使用fluent属性,getter和setter方法的方法名都是属性名,且setter方法返回当前对象

@Data
@Accessors(fluent = true)
class User {
    private Integer id;
    private String name;

    // 生成的getter和setter方法如下,方法体略
    public Integer id(){}
    public User id(Integer id){}
    public String name(){}
    public User name(String name){}
}

@Accessors(chain = true)

使用chain属性,setter方法返回当前对象

@Data
@Accessors(chain = true)
class User {
    private Integer id;
    private String name;

    // 生成的setter方法如下,方法体略
    public User setId(Integer id){}
    public User setName(String name){}
}

@Accessors(prefix = “f”)

使用prefix属性,getter和setter方法会忽视属性名的指定前缀(遵守驼峰命名)

@Data
@Accessors(prefix = "f")
class User {
    private Integer fId;
    private String fName;

    // 生成的getter和setter方法如下,方法体略
    public Integer id(){}
    public void id(Integer id){}
    public String name(){}
    public void name(String name){}
}

Lombok 所有注解如下:

  • val:用在局部变量前面,相当于将变量声明为 final;
  • @NonNull:给方法参数增加这个注解会自动在方法内对该参数进行是否为空的校验,如果为空,则抛出 NPE(NullPointerException);
  • @Cleanup:自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成 try-finally 这样的代码来关闭流;
  • @Getter/@Setter:用在属性上,再也不用自己手写 setter 和 getter 方法了,还可以指定访问范围;
  • @ToString:用在类上可以自动覆写 toString 方法,当然还可以加其他参数,例如 @ToString(exclude=”id”) 排除 id 属性,或者 @ToString(callSuper=true, includeFieldNames=true) 调用父类的 toString 方法,包含所有属性;
  • @EqualsAndHashCode:用在类上自动生成 equals 方法和 hashCode 方法;
  • @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor:用在类上,自动生成无参构造和使用所有参数的构造函数以及把所有 @NonNull 属性作为参数的构造函数,如果指定 staticName=”of” 参数,同时还会生成一个返回类对象的静态工厂方法,比使用构造函数方便很多;
  • @Data:注解在类上,相当于同时使用了 @ToString、@EqualsAndHashCode、@Getter、@Setter 和 @RequiredArgsConstrutor 这些注解,对于 POJO 类十分有用;
  • @Value:用在类上,是 @Data 的不可变形式,相当于为属性添加 final 声明,只提供 getter 方法,而不提供 setter 方法;
  • @Builder:用在类、构造器、方法上,为你提供复杂的 builder APIs,让你可以像如下方式一样调用Person.builder().name(“xxx”).city(“xxx”).build();
  • @SneakyThrows:自动抛受检异常,而无需显式在方法上使用 throws 语句;
  • @Synchronized:用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性 或LOCK,而 Java 中的 synchronized 关键字锁对象是 this,锁在 this 或者自己的类对象上存在副作用,就是你不能阻止非受控代码去锁 this 或者类对象,这可能会导致竞争条件或者其它线程错误;
  • @Getter(lazy=true):可以替代经典的 Double Check Lock 样板代码;
  • @Log:根据不同的注解生成不同类型的 log 对象,但是实例名称都是 log,有六种可选实现类
    • @CommonsLog Creates log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
    • @Log Creates log = java.util.logging.Logger.getLogger(LogExample.class.getName());
    • @Log4j Creates log = org.apache.log4j.Logger.getLogger(LogExample.class);
    • @Log4j2 Creates log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
    • @Slf4j Creates log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
    • @XSlf4j Creates log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

val示例

public static void main(String[] args) {
    val sets = new HashSet<String>();
    val lists = new ArrayList<String>();
    val maps = new HashMap<String, String>();
    //=>相当于如下
    final Set<String> sets2 = new HashSet<>();
    final List<String> lists2 = new ArrayList<>();
    final Map<String, String> maps2 = new HashMap<>();
}

@NonNull示例

public void notNullExample(@NonNull String string) {
    string.length();
}
//=>相当于
public void notNullExample(String string) {
    if (string != null) {
        string.length();
    } else {
        throw new NullPointerException("null");
    }
}

@Cleanup示例

public static void main(String[] args) {
    try {
        @Cleanup InputStream inputStream = new FileInputStream(args[0]);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    //=>相当于
    InputStream inputStream = null;
    try {
        inputStream = new FileInputStream(args[0]);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

@Getter/@Setter示例

@Setter(AccessLevel.PUBLIC)
@Getter(AccessLevel.PROTECTED)
private int id;
private String shap;

@ToString示例

@ToString(exclude = "id", callSuper = true, includeFieldNames = true)
public class LombokDemo {
    private int id;
    private String name;
    private int age;
    public static void main(String[] args) {
        //输出LombokDemo(super=LombokDemo@48524010, name=null, age=0)
        System.out.println(new LombokDemo());
    }
}

@EqualsAndHashCode示例

@EqualsAndHashCode(exclude = {"id", "shape"}, callSuper = false)
public class LombokDemo {
    private int id;
    private String shap;
}

@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor示例

@NoArgsConstructor
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor
public class LombokDemo {
    @NonNull
    private int id;
    @NonNull
    private String shap;
    private int age;
    public static void main(String[] args) {
        new LombokDemo(1, "circle");
        //使用静态工厂方法
        LombokDemo.of(2, "circle");
        //无参构造
        new LombokDemo();
        //包含所有参数
        new LombokDemo(1, "circle", 2);
    }
}

@Data示例

import lombok.Data;
@Data
public class Menu {
    private String shopId;
    private String skuMenuId;
    private String skuName;
    private String normalizeSkuName;
    private String dishMenuId;
    private String dishName;
    private String dishNum;
    //默认阈值
    private float thresHold = 0;
    //新阈值
    private float newThresHold = 0;
    //总得分
    private float totalScore = 0;
}

@Value示例

@Value
public class LombokDemo {
    @NonNull
    private int id;
    @NonNull
    private String shap;
    private int age;
    //相当于
    private final int id;
    public int getId() {
        return this.id;
    }
    ...
}

@Builder示例

@Builder
public class BuilderExample {
    private String name;
    private int age;
    @Singular
    private Set<String> occupations;
    public static void main(String[] args) {
        BuilderExample test = BuilderExample.builder().age(11).name("test").build();
    }
}

@SneakyThrows示例

import lombok.SneakyThrows;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
public class Test {
    @SneakyThrows()
    public void read() {
        InputStream inputStream = new FileInputStream("");
    }
    @SneakyThrows
    public void write() {
        throw new UnsupportedEncodingException();
    }
    //相当于
    public void read() throws FileNotFoundException {
        InputStream inputStream = new FileInputStream("");
    }
    public void write() throws UnsupportedEncodingException {
        throw new UnsupportedEncodingException();
    }
}

@Synchronized示例

public class SynchronizedDemo {
    @Synchronized
    public static void hello() {
        System.out.println("world");
    }
    //相当于
    private static final Object $LOCK = new Object[0];
    public static void hello() {
        synchronized ($LOCK) {
            System.out.println("world");
        }
    }
}

@Getter(lazy = true)

public class GetterLazyExample {
    @Getter(lazy = true)
    private final double[] cached = expensive();
    private double[] expensive() {
        double[] result = new double[1000000];
        for (int i = 0; i < result.length; i++) {
            result[i] = Math.asin(i);
        }
        return result;
    }
}

// 相当于如下所示: 

import java.util.concurrent.atomic.AtomicReference;
public class GetterLazyExample {
    private final AtomicReference<java.lang.Object> cached = new AtomicReference<>();
    public double[] getCached() {
        java.lang.Object value = this.cached.get();
        if (value == null) {
            synchronized (this.cached) {
                value = this.cached.get();
                if (value == null) {
                    final double[] actualValue = expensive();
                    value = actualValue == null ? this.cached : actualValue;
                    this.cached.set(value);
                }
            }
        }
        return (double[]) (value == this.cached ? null : value);
    }
    private double[] expensive() {
        double[] result = new double[1000000];
        for (int i = 0; i < result.length; i++) {
            result[i] = Math.asin(i);
        }
        return result;
    }
}

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 300点赞 642047浏览

随机文章
MyBatis笔记5—properties(外部配置)
6年前
SpringCloud—Hystrix(五)请求合并
5年前
SpringCloud—Eureka(二)(Ribbon)
5年前
Java—并发编程(六)JUC锁 – (10) Semaphore
4年前
Spring—IOC容器(构建)
3年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:2004 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 642047 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付