zoukankan      html  css  js  c++  java
  • lombok

    一、Lombok背景介绍

    官方介绍如下:

    Project Lombok makes java a spicier language by adding 'handlers' that know how to build and compile simple, boilerplate-free, not-quite-java code.
    

    大致意思是Lombok通过增加一些“处理程序”,可以让java变得简洁、快速。

    二、Lombok安装

    Lombok的使用非常简单:

    2.1、引入相应的maven包

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

    2.2、添加IDE工具对Lombok的支持

    IDEA中引入Lombok支持如下:

    点击File-- Settings设置界面,安装Lombok插件:

    img

    点击File-- Settings设置界面,开启 AnnocationProcessors: 开启该项是为了让Lombok注解在编译阶段起到作用。 img

    Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。

    Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

    Lombok的使用跟引用jar包一样,可以在官网(https://projectlombok.org/download)下载jar包,也可以使用maven添加依赖:

    三、Lombok使用详解

    Lombok 提供注解方式来提高代码的简洁性,常用注解概览:

    • val:用在局部变量前面,相当于将变量声明为final
    • @Data:注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法,相当于同时加上以下注解@Setter @Getter,@ToString,@EqualsAndHashCode
    • @Value: 用在类上,是@Data的不可变形式,相当于为属性添加final声明,只提供getter方法,而不提供setter方法
    • @Setter、@Getter:注解在类和属性上;为属性提供 setting、getting 方法
    • @Getter(lazy=true) : 可以替代经典的Double Check Lock样板代码
    • @ToString:生成toString方法,默认情况下,会输出类名、所有属性,属性按照顺序输出,以逗号分割。
    • @EqualsAndHashCode:实现equals()方法和hashCode()方法
    • @Builder:构建 建造者模式
    • @NonNull:该注解快速判断是否为空,如果为空,则抛出java.lang.NullPointerException
    • @Synchronized:该注解自动添加到同步机制,有趣的是,生成的代码并不是直接锁方法,而是锁代码块, 作用范围是方法上
    • @Log : 根据不同的注解生成不同类型的log对象,但是实例名称都是log,有六种可选实现类
    • @NoArgsConstructor:注解在类上; 会生成一个返回类对象的静态工厂方法。
    • @RequiredArgsConstructor:注解在类上;为类提供一个部分参的构造方法(使用类中所有带有@NonNull注解的或者带有final修饰的成员变量生成对应的构造方法)
    • @AllArgsConstructor:注解在类上;为类提供一个全参的构造方法
    • @Cleanup:用于确保已分配的资源被释放,如IO的连接关闭
    • @SneakyThrows:抛异常
    • @Accessors: 用于配置getter和setter方法的生成结果

    3.1、val

    用在局部变量前面,相当于将变量声明为final

    public static void main(String[] args) {
            /**
             * str1 和 str2的两种定义方法都可以
             */
            val str1="abc";
            final String str2="abc";
        }
    

    3.2、@Data

    注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法,相当于同时加上以下注解@Setter @Getter,@ToString,@EqualsAndHashCode

    @Data
    public class Book {
    
        private  String isbn;
        private String book_name;
        private String price;
    }
    

    效果同@Value

    3.3、@Value

    @Value
    @AllArgsConstructor
    public class Book {
    
        private  String isbn;
    }
    

    相当于

    public class Book {
    
        private final String isbn;
      
      	public String getIsbn() {
            return isbn;
        }
    }
    

    调用、

     Book book = new Book("1");
    

    3.4、@Getter@Setter

    注解在类和属性上;为属性提供 setting、getting 方法

    public class Book {
        
        @Setter@Getter
        private  String isbn;
    }
    
    

    3.5、@Getter(lazy=true)

    如果 Bean 的一个字段的初始化是代价比较高的操作,比如加载大量的数据;同时这个字段并不是必定使用的。那么使用懒加载机制,可以保证节省资源。

    懒加载机制,是对象初始化时,该字段并不会真正的初始化,而是第一次访问该字段时才进行初始化字段的操作。

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

    3.6、@ToString

    生成 toString 方法,默认情况下,会输出类名、所有属性,属性按照顺序输出,以逗号分割。但需要注意的是:@ToString有多个属性可以进一步设置:

    • callSuper 是否输出父类的toString方法,默认为false
    • includeFieldNames 是否包含字段名称,默认为true
    • exclude 排除生成tostring的字段
    @ToString(callSuper = true,exclude ={"name"})
    public class Person {
        private String name;
        private String address;
    }
    

    3.7、@EqualsAndHashCode

    用在类上,自动生成 equals 方法和 hashCode 方法

    参数exclude排除一些属性 ; 参数of指定仅使用哪些属性 ; 默认仅使用该类中定义的属性且不调用父类的方法 (即 callSuper=false)。

    //父类
    public class Person {
        private String name;
        private String sex;
    
        public Person(String name, String sex) {
            this.name = name;
            this.sex = sex;
        }
    }
    
    @EqualsAndHashCode(exclude = {"className"},callSuper = false)
    public class Student extends Person{
        @Getter@Setter
        private int age;
        @Getter@Setter
        private String className;
    
        public Student(String name,String sex,int age,String className) {
            super(name,sex);
            this.age = age;
            this.className = className;
        }
    }
    
    Student s1 = new Student("hresh","man",22,"Lv3");
    Student s2 = new Student("hresh","woman",22,"Lv5");
    System.out.println(s1.equals(s2));//true
    

    解析: 子类实现@EqualsAndHashCode(callSuper = false) ,不调用父类的属性,那么子类属性里面的相同的话,那 hashcode 的值就相同,再加上排除对 className 属性的比对,所以代码里面的2个对象的 equals 方法的返回值是 true 。

    3.8、@NonNull

    该注解快速判断是否为空,如果为空,则抛出 java.lang.NullPointerException

    public class Person {
    
        private String name;
    
        @Setter@Getter@NonNull
        private List<Person> member;
    }
    

    等价于:

    @NonNull
    private List<Person> members;
    
    public Family(@NonNull final List<Person> members) {
        if (members == null) throw new java.lang.NullPointerException("members");
        this.members = members;
    }
    
    @NonNull
    public List<Person> getMembers() {
        return members;
    }
    
    public void setMembers(@NonNull final List<Person> members) {
        if (members == null) throw new java.lang.NullPointerException("members");
        this.members = members;
    }
    

    3.8、@Synchronized

    该注解自动添加到同步机制,有趣的是,生成的代码并不是直接锁方法,而是锁代码块, 作用范围是方法上。

    private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");
    
    @Synchronized
    public String synchronizedFormat(Date date) {
        return format.format(date);
    }
    

    等价于:

    private final java.lang.Object $lock = new java.lang.Object[0];
    private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");
    
    public String synchronizedFormat(Date date) {
        synchronized ($lock) {
            return format.format(date);
        }
    }
    

    3.9、@NoArgsConstructor

    注解在类上;为类提供一个无参的构造方法

    @Data
    @NoArgsConstructor(staticName = "init")
    public class Student {
        private long id = new Long(0);
        private String name = " ";
        private String className = " ";
    }
    

    等价于:

    @Data
    //@NoArgsConstructor(staticName = "init")
    public class Student {
        private long id = new Long(0);
        private String name = " ";
        private String className = " ";
    
        public static Student init(){
            return new Student();
        }
    }
    

    3.10、@AllArgsConstructor

    注解在类上,为类提供一个全参的构造方法

    @Data
    @AllArgsConstructor
    public class Student {
        private long id = new Long(0);
        private String name = " ";
        private String className = " ";
    }
    

    相当于:

    @Data
    public class Student {
        private long id = new Long(0);
        private String name = " ";
        private String className = " ";
    
        public Student(long id, String name, String className) {
            this.id = id;
            this.name = name;
            this.className = className;
        }
    }
    

    3.11、@RequiredArgsConstructor

    注解在类上;为类提供一个部分参的构造方法(使用类中所有带有@NonNull注解的或者带有final修饰的成员变量生成对应的构造方法)

    @Data
    @RequiredArgsConstructor
    public class Student {
        @NonNull
        private long id ;
        @NonNull
        private String name ;
        private String className;
    
    }
    

    实际调用:

    Student student = new Student(101,"hresh");
    System.out.println(student);
    

    3.12、@Cleanup

    注释可用于确保已分配的资源被释放,如 IO 的连接关闭。

    public void testCleanUp() {
        try {
            @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();
            baos.write(new byte[] {'Y','e','s'});
            System.out.println(baos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    等价于:

    public void testCleanUp() {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                baos.write(new byte[]{'Y', 'e', 's'});
                System.out.println(baos.toString());
            } finally {
                baos.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    3.13、@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);
    

    已slf4j 日志对象为例。

    注解在类上;为类提供一个 属性名为log 的 slf4j 日志对象

    @Slf4j
    public class StudentTest {
    
        public static void main(String[] args) {
            log.info("Here is some INFO");
        }
    }
    

    等价于:

     public class StudentTest {
    
        public static Logger log = LoggerFactory.getLogger(StudentTest.class);
    
        public static void main(String[] args) {
            log.info("Here is some INFO");
        }
    }
    

    2.14、@Accessors

    Accessor 的中文含义是存取器,@Accessors 用于配置 getter 和 setter 方法的生成结果,下面介绍三个属性

    1、 fluent

    fluent 的中文含义是流畅的,设置为true 则 生成的get/set方法则没有 set/get 前缀,默认为 false 。

    @Data
    @Accessors(fluent = true)
    public class Student {
        private long id = new Long(0);
        private String name = " ";
        private String className = " ";
    
    }
    

    实际调用

    public class StudentTest {
    
        public static void main(String[] args) {
            Student student = new Student();
            student.name("hresh");//相当于SetName()
            student.className("Lv5");
            System.out.println(student);
            System.out.println(student.name());//相当于getName()
        }
    }
    

    2、 chain

    chain 的中文含义是链式的,为一个布尔值, 如果为 true 生成的 set 方法返回 this,为 false 生成的 set 方法是 void 类型。 默认为 false,除非当 fluent 为 true时,chain 默认则为 true 。

    @Setter
    @Getter
    @Accessors(chain = true)
    public class User {
        private String id;
        private String name;
        private Integer age;
    }
    
    public static void main(String[] args) {
        //使用@Accessors(chain = true)
        User userChain = new User();
        userChain.setId("1").setName("chain").setAge(1);
    }
    

    3、 prefix

    prefix 为一系列 string 类型,可以指定前缀,生成 get/set 方法时会去掉指定的前缀 。

    @Data
    @Accessors(prefix = "n")
    public class Student {
    //    private long id = new Long(0);
        private String nAme = " ";
        private String name = " ";
        private String className = " ";
        private int nId  = new Integer(0);
    }
    

    实际调用:

    public class StudentTest {
    
        public static void main(String[] args) {
            Student student = new Student();
    
            student.setId(101);
            System.out.println(student.getId());
            student.setAme("hresh");
            student.setName("hresh");
            System.out.println(student);
        }
    }
    

    需要注意的是,此时类中的属性命名存在这样的规则,指定前缀+大写字符,像上述代码中如果属性为 name 而非 nAme,则不成立。

    2.15、@SneakyThrows

    自动抛受检异常,而无需显式在方法上使用 throws 语句

    @SneakyThrows
    public void read(){
        InputStream inputStream = new FileInputStream("");
    }
    //相当于
    public void read() throws FileNotFoundException {
        InputStream inputStream = new FileInputStream("");
    }
    

    2.16、@Builder

    用在类、构造器、方法上,为你提供复杂的 builder APIs

    @Builder
    @Data
    public class Student {
        private String name ;
        private int age;
    }
    

    实际调用:

    public class StudentTest {
    
        public static void main(String[] args) {
            Student student = Student.builder().name("hresh").age(22).build();
        }
    }
    

    等价于:

    public class Student {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public static Builder builder(){
            return new Builder();
        }
        public static class Builder{
            private String name;
            private int age;
            public Builder name(String name){
                this.name = name;
                return this;
            }
    
            public Builder age(int age){
                this.age = age;
                return this;
            }
    
            public Student build(){
                Student student = new Student();
                student.setAge(age);
                student.setName(name);
                return student;
            }
        }
    }
    

    2.17、@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());
    
    }
    
  • 相关阅读:
    行内元素知识点
    WPF可视化控件打印
    C#模拟网站用户登录
    不同版本的浏览器代理编码
    WPF弹出对话确认框
    MSDN中HttpWebRequest/HttpWebResponse用法
    C#Http编程
    WPF ICommand 用法
    详述.NET里class和struct的异同
    WPF页面切换及弹窗
  • 原文地址:https://www.cnblogs.com/jdy1022/p/13969967.html
Copyright © 2011-2022 走看看