lombok实践

4 篇文章 0 订阅
为什么要用lombo
  1. 个别javaBean的属性很多(多的有100多个,生成Setter/Getter太多,并且阅读代码体验很不好)
  2. 有的大佬在getter/setter里写业务逻辑或者数据处理导致错误的认为是属性本身的值错误(我并不认为在setter/getter里面添加业务逻辑有什么好的)
  3. 生成getter/setter的代码格式不统一(有的setter可能会返回this,有的是void,有的使用isXXX,有的使用getXXX)
  4. 增加属性的同时需要重新生成toString、equals等方法(假如有的话)

使用lombok带来好处:

  1. 简化JavaBean定义
  2. 提高开发效率
  3. 标准化、规范化JavaBean定义
引入lombok

lombok本身只需要引入jar就可以使用,但是为了编程的舒适性(编译不报错,能自动补全等)
还是需要IDE插件支持,以IDEA为例子(别的IDE可以看看插件github上有没有,详细地址见本文末尾提供的链接):
跟普通的IDEA插件一样,直接搜索lombok然后直接安装就可以,可能会提示需要jar引入也可能不会,然后重启IDEA,插件就装好了装好就跟跟下图一样。

在这里插入图片描述
引入依赖:

maven:

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

jar:
下载页

怎么使用lombok

直接使用注解就可以使用lombok。

  • @Getter/@Setter
    很明显这两个注解的作用是生成Setter/getter,直接打注解在属性上就可以。
package demo;


import lombok.Getter;
import lombok.Setter;

public class UserDemo {

    /**
     * 姓名
     */
    @Setter
    private String name;

    /**
     * 年龄
     */
    @Getter
    private Integer age;

    /**
     * 联系电话
     */
    @Setter
    @Getter
    private  String mobile;

}

对应生成的class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package demo;

public class UserDemo {
    private String name;
    private Integer age;
    private String mobile;

    public UserDemo() {
    }

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

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

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getMobile() {
        return this.mobile;
    }
}
  • @ToString
    生成toString方法,其中注解可以设置·exclude·的值来设置哪些属性不需要被打印出来,callSuper则可以控制是不是调用父类的toString方法。
package demo;


import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@ToString
public class UserDemo {

    /**
     * 姓名
     */
    @Setter
    private String name;

    /**
     * 年龄
     */
    @Getter
    private Integer age;

    /**
     * 联系电话
     */
    @Setter
    @Getter
    private  String mobile;

}

对应生成的class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package demo;

public class UserDemo {
    private String name;
    private Integer age;
    private String mobile;

    public UserDemo() {
    }

    public String toString() {
        return "UserDemo(name=" + this.name + ", age=" + this.getAge() + ", mobile=" + this.getMobile() + ")";
    }

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

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

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getMobile() {
        return this.mobile;
    }
}

  • @EqualsAndHashCode
    直接根据属性生成equalshashCode方法,这个方法有一个地方需要注意的是,假如类是一个子类,单纯的增加@EqualsAndHashCode注解,是不会调用父类的方法的,这个时候需要增加callSuper=true,完整的注解应该是@EqualsAndHashCode(callSuper = true)
package demo;


import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@ToString
@EqualsAndHashCode
public class UserDemo {

    /**
     * 姓名
     */
    @Setter
    private String name;

    /**
     * 年龄
     */
    @Getter
    private Integer age;

    /**
     * 联系电话
     */
    @Setter
    @Getter
    private  String mobile;

}

对应生成的class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package demo;

public class UserDemo {
    private String name;
    private Integer age;
    private String mobile;

    public UserDemo() {
    }

    public String toString() {
        return "UserDemo(name=" + this.name + ", age=" + this.getAge() + ", mobile=" + this.getMobile() + ")";
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof UserDemo)) {
            return false;
        } else {
            UserDemo other = (UserDemo)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$name = this.name;
                    Object other$name = other.name;
                    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$mobile = this.getMobile();
                Object other$mobile = other.getMobile();
                if (this$mobile == null) {
                    if (other$mobile != null) {
                        return false;
                    }
                } else if (!this$mobile.equals(other$mobile)) {
                    return false;
                }

                return true;
            }
        }
    }

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

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

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

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

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getMobile() {
        return this.mobile;
    }
}

  • @NoArgsConstructor/@AllArgsConstructor
    这两个注解都是用于生成构造函数的,一个是没有参数的,一个是所有参数的。
    注解本身还有个可选额属性access,可以设置方法的访问修饰符(publicprivate等)
package demo;


import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;


@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class UserDemo {

    /**
     * 姓名
     */
    @Setter
    private String name;

    /**
     * 年龄
     */
    @Getter
    private Integer age;

    /**
     * 联系电话
     */
    @Setter
    @Getter
    private  String mobile;

}

对应生成的calsss

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package demo;

public class UserDemo {
    private String name;
    private Integer age;
    private String mobile;

    public String toString() {
        return "UserDemo(name=" + this.name + ", age=" + this.getAge() + ", mobile=" + this.getMobile() + ")";
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof UserDemo)) {
            return false;
        } else {
            UserDemo other = (UserDemo)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$name = this.name;
                    Object other$name = other.name;
                    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$mobile = this.getMobile();
                Object other$mobile = other.getMobile();
                if (this$mobile == null) {
                    if (other$mobile != null) {
                        return false;
                    }
                } else if (!this$mobile.equals(other$mobile)) {
                    return false;
                }

                return true;
            }
        }
    }

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

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

    public UserDemo() {
    }

    public UserDemo(String name, Integer age, String mobile) {
        this.name = name;
        this.age = age;
        this.mobile = mobile;
    }

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

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

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getMobile() {
        return this.mobile;
    }
}

  • @NonNull
    切记不是@NotNull,@NotNull是别的注解。
    这个注解其实有点点鸡肋,其实就是对于对打了注解的参数进行一个判空,假如有空则直接抛出空指针异常,这个异常抛出的逻辑会生成在构造函数和Setter中。
package demo;


import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;
import lombok.ToString;


@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class UserDemo {

    /**
     * 姓名
     */
    @Setter
    private String name;

    /**
     * 年龄
     */
    @Getter
    private Integer age;

    /**
     * 联系电话
     */
    @Setter
    @Getter
    @NonNull
    private  String mobile;

}

对应生成的calss

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package demo;

import lombok.NonNull;

public class UserDemo {
    private String name;
    private Integer age;
    @NonNull
    private String mobile;

    public String toString() {
        return "UserDemo(name=" + this.name + ", age=" + this.getAge() + ", mobile=" + this.getMobile() + ")";
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof UserDemo)) {
            return false;
        } else {
            UserDemo other = (UserDemo)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$name = this.name;
                    Object other$name = other.name;
                    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$mobile = this.getMobile();
                Object other$mobile = other.getMobile();
                if (this$mobile == null) {
                    if (other$mobile != null) {
                        return false;
                    }
                } else if (!this$mobile.equals(other$mobile)) {
                    return false;
                }

                return true;
            }
        }
    }

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

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

    public UserDemo() {
    }

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

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

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

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

    @NonNull
    public String getMobile() {
        return this.mobile;
    }
}

  • @RequiredArgsConstructor
    包含参数的构造函数,配合@NonNull使用,生成一个只包含@NonNull属性的构造函数。需要注意的是假如类里面没有属性加了 @NonNull注解,那么@RequiredArgsConstructor注解生成的将是一个没有参数的构造函数,在这个时候要是和@NoArgsConstructor注解一起使用则会直接编译错误。
package demo;


import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;


@ToString
@EqualsAndHashCode
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
public class UserDemo {

    /**
     * 姓名
     */
    @Setter
    private String name;

    /**
     * 年龄
     */
    @Getter
    @NonNull
    private Integer age;

    /**
     * 联系电话
     */
    @Setter
    @Getter
    @NonNull
    private  String mobile;

}

对应生成的class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package demo;

import lombok.NonNull;

public class UserDemo {
    private String name;
    @NonNull
    private Integer age;
    @NonNull
    private String mobile;

    public String toString() {
        return "UserDemo(name=" + this.name + ", age=" + this.getAge() + ", mobile=" + this.getMobile() + ")";
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof UserDemo)) {
            return false;
        } else {
            UserDemo other = (UserDemo)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$name = this.name;
                    Object other$name = other.name;
                    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$mobile = this.getMobile();
                Object other$mobile = other.getMobile();
                if (this$mobile == null) {
                    if (other$mobile != null) {
                        return false;
                    }
                } else if (!this$mobile.equals(other$mobile)) {
                    return false;
                }

                return true;
            }
        }
    }

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

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

    public UserDemo() {
    }

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

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

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

    @NonNull
    public Integer getAge() {
        return this.age;
    }

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

    @NonNull
    public String getMobile() {
        return this.mobile;
    }
}

  • @Data
    这个注解是综合了@ToString,@EqualsAndHashCode,@Getter,@Setter,@RequiredArgsConstructor五个注解,注意的是这些注解都是默认使用的默认状态,则@ToString@EqualsAndHashCode不会调用父类方法,生成所有属性相关的方法,@Setter生成非final修饰的属性,假如不满足需求,那就在@Data的基础上单独再加上注解。
package demo;


import lombok.Data;


@Data
public class UserDemo {

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 联系电话
     */
    private  String mobile;

}

对应生成的class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package demo;

public class UserDemo {
    private String name;
    private Integer age;
    private String mobile;

    public UserDemo() {
    }

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

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

    public String getMobile() {
        return this.mobile;
    }

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

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

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof UserDemo)) {
            return false;
        } else {
            UserDemo other = (UserDemo)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$mobile = this.getMobile();
                Object other$mobile = other.getMobile();
                if (this$mobile == null) {
                    if (other$mobile != null) {
                        return false;
                    }
                } else if (!this$mobile.equals(other$mobile)) {
                    return false;
                }

                return true;
            }
        }
    }

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

    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 $mobile = this.getMobile();
        result = result * 59 + ($mobile == null ? 43 : $mobile.hashCode());
        return result;
    }

    public String toString() {
        return "UserDemo(name=" + this.getName() + ", age=" + this.getAge() + ", mobile=" + this.getMobile() + ")";
    }
}

  • @Builder
    作用在于在目标类中创建一个静态内部类,可以用内部类以链式调用的方式很方便的创建对象。
package com.fangdd.nh.organization;

import lombok.Builder;


@Builder
public class UserDemo {

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 联系电话
     */
    private  String mobile;

}

对应生成的class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.fangdd.nh.organization;

public class UserDemo {
    private String name;
    private Integer age;
    private String mobile;

    UserDemo(String name, Integer age, String mobile) {
        this.name = name;
        this.age = age;
        this.mobile = mobile;
    }

    public static UserDemo.UserDemoBuilder builder() {
        return new UserDemo.UserDemoBuilder();
    }

    public static class UserDemoBuilder {
        private String name;
        private Integer age;
        private String mobile;

        UserDemoBuilder() {
        }

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

        public UserDemo.UserDemoBuilder age(Integer age) {
            this.age = age;
            return this;
        }

        public UserDemo.UserDemoBuilder mobile(String mobile) {
            this.mobile = mobile;
            return this;
        }

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

        public String toString() {
            return "UserDemo.UserDemoBuilder(name=" + this.name + ", age=" + this.age + ", mobile=" + this.mobile + ")";
        }
    }
}

注意事项和小坑
  • 实际开发中用到最多的是直接@Data注解,对于普通的JavaBean基本上满足需求了。但是需要注意的是@Data默认的构造函数是用@RequiredArgsConstructor所以可能会收到@nonNull的影响。
  • 对于使用了@Data但是有个别属性不需要生成Setter/Getter的可以设置@Getter(AccessLevel.NONE)@Setter(AccessLevel.NONE)来显示的表示属性不需要生成Setter/Getter, AccessLevel.NONE在很多lombok注解种都可以使用。
  • 关于Boolean属性生成Getter的问题:lombok生成的都是getXXX,setXXX这样的形式,假如需要对Boolean属性特殊生成isXXX,则需要自己生成,然后标记属性不需要lombok来生成。至于为什么不生成isXXX,官方给出的原话:

    Any variation on boolean will not result in using the is prefix instead of the get prefix; for example, returning java.lang.Boolean results in a get prefix, not an is prefix.

虽然没说为什么,但是就是暂时不支持,不知以后会不会支持。

小结

构造函数的生成可以根据实际情况选择,但是
lombok的使用还是需要根据实际框架和业务的需求来选择。并不是所有场景都适用。对于简单的Bean或者需要统一标准的Bean的话还是比较推荐使用lombok。
这里所讲的注解基本上都是我用过的,没讲到的可以看看官方文档,根据实际需要选择。

lombok相关文档以及git地址

lombok 官方
lombok GitHub地址
lombok IDEA插件GitHub地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值