• LomBok


    最近,偶然看到东西——能够在开发的过程中用注解的方式,简化实体类。看起来还不错的样子,我挺喜欢,可以了解了解。说不定哪天就用上了。

    于是我记下了学习笔记。上目录。

    目录

    什么是Lombok

    根据百度百科的解释。

    Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能。不需要再写getter、setter或equals方法,只要有一个注解,你的类就有一个功能齐全的构建器、自动记录变量等等。

    也就是说,Lombok是为了简化JavaBean代码。

    Lombok的作用——简化代码

    Lombok的作用是简化代码。
    按照我们通常的方法,角色的实体类代码如下:

     1 public class Role {
     2     private int rid;
     3     private String rname;
     4     private String level;
     5 
     6     public int getRid() {
     7         return rid;
     8     }
     9 
    10     public void setRid(int rid) {
    11         this.rid = rid;
    12     }
    13 
    14     public String getRname() {
    15         return rname;
    16     }
    17 
    18     public void setRname(String rname) {
    19         this.rname = rname;
    20     }
    21 
    22     public String getLevel() {
    23         return level;
    24     }
    25 
    26     public void setLevel(String level) {
    27         this.level = level;
    28     }
    29 
    30     @Override
    31     public String toString() {
    32         return "Role{" +
    33                 "rid=" + rid +
    34                 ", rname='" + rname + '\'' +
    35                 ", level='" + level + '\'' +
    36                 '}';
    37     }
    38 }
    Role

    如果使用lombok,只需要如下代码:

    1 @Data
    2 public class Role {
    3     private int rid;
    4     private String rname;
    5     private String level;
    6 }
    View Code

    Lombok的优缺点

    Lombok的优点

    • 代码简洁

    Lombok的缺点

    • 强迫性。因为Lombok的使用要求开发者一定要在IDE中安装对应的插件。只要一个人安装了Lombok,其他人也需要安装,否则编译报错。
    • 可读性和调试性降低。在代码中使用了Lombok,确实可以帮忙减少很多代码,因为Lombok会帮忙自动生成很多代码。我们不能直接知道类中的getter方法被哪些类引用。
    • 不了解底层原理,容易出错。在使用Lombok过程中,如果对于各种注解的底层原理不理解的话,很容易产生意想不到的结果。

    举一个简单的例子,我们知道,当我们使用@Data定义一个类的时候,会自动帮我们生成 equals() 方法 。但是如果只使用了 @Data ,而不使用 equalsAndHashCode(callSuper=true) 的话,会默认是 @EqualsAndHashCode(callSuper=false) ,这时候生成的 equals() 方法只会比较子类的属性,不会考虑从父类继承的属性,无论父类属性访问权限是否开放。

    • 影响升级。如果我们需要升级到某个新版本的JDK的时候,若其中的特性在Lombok中不支持的话就会受到影响。
    • 破坏抽象。如果我们在代码中直接使用Lombok,那么他会自动帮我们生成getter、setter 等方法,这就意味着,一个类中的所有参数都自动提供了设置和读取方法

    对应Lombok缺点?

    强迫性

    对我来说,安装一个插件也不是很费事。当然,如果你要和人合作,他不愿意安装,那确实很难——相比起来,get、set、equals、toString等方法点几下鼠标和快捷键就生成了。所以,这个缺点主要是“势”。很多东西,用的人越多,维护他的人也越多,它的功能才能优化。

    注:最新的IDEA似乎不需要安装插件,因为在IDEA中集成了。

    可读性和调试性降低

    我觉得可读性还是提高了,毕竟重复的代码减少了。其实通过IDEA可以很方便的找到某个属性的getter方法都被哪些类引用,这一点有待于进一步学习。

    不了解底层原理,容易出错

    每一个工具都有可能遇到坑,额,这个坑……很难理解吗?如果要开发越多人使用的东西,确实越需要谨慎——哪怕是看起来比较简单的新东西。所以,使用工具,确实要对它有所了解,否则容易出错。我们还是需要深度,更何况,Lombok没有特别深。

    破坏抽象

    这个要看使用场景。以我现在有限的代码来说,几乎所有参数都提供了get和set方法,并没有那么个性化的权限。如果真有个性化的权限,我希望使用注释的方式,这样更加一目了然。

    很显然,类A聚集在一起的一行,或者两行代码,就能让我们知道属性的读取,或者写权限;类B,如果属性比较多,似乎相对看起来就没有那么方便了。需要个性化配置权限的时候,带有get和set的注解更一目了然。
    Lombok中带有这样的注解:
    @Setter/@Getter : 生成set和get方法。
    影响升级

    如果遇到这个问题,确实比较头疼,不知道发生它的概率。

    不过,一般来说。以我有限的经验来说,同一个项目不会去随便升级JDK。难保一些插件和版本不对应。

    个人看法

    总之,lombok代码的思想还是很好的,它让代码的可读性提高了很多(写代码的时间倒是看不出节约,因为IDEA(或其他工具)都能快速生成get,set方法)。
    对于他的缺点,大多数是因为固有的习惯,让很多人不适应;影响升级的问题,就像我们完成一件事情时,遇到的一些问题。如果更多的人接受这一思想,那么必定能够得到处理。
    现实工作中,我们要人接受同一个工具、同一件事情不容易。可以提出自己的意见,但真正如果落实,要以实际的沟通为主。

    Lombok原理

    它的注解是在编译过程就生效的。其他的,我没关心……

    不好意思,偶尔的不求甚解。

    Lombok的使用准备(Idea)

    使用准备包括两部,安装插件和添加项目依赖。

    注:最新版的Ida似乎已经自带lombok插件(看来她是大势所趋)。

    Lombok的安装

    1. 使用快捷键【Crlt+Alt+S】(或点击菜单栏【File】—> 【Settings】)
    2. 找到Lombox插件,并点击安装。等待安装完成。

    安装完成后需要重启Idea。

    添加项目依赖

    打开pom.xml文件,加上项目依赖。

    1 <dependency>
    2     <groupId>org.projuectlombok</groupId>
    3     <artifactId>lombok</artifactId>
    4     <version>1.16.10</version>
    5 </dependency>

    正式使用Lombok

    接下来,我们看看Lombox的常用注解有哪些。

    写一个JavaBean

    写一个简单的实体类。这也将是以后写实体类的常用注释。

    1 @Data
    2 public class User {
    3     private  Integer id;
    4     private  String username;
    5     private String password;
    6     private String phone;
    7     private String email;
    8 }
    User

    按【Alt + 7】,可以看到项目的结构如下。

    可以知道,生成了一下类:

    • 类的构造方法
    • 所有属性的get和set方法
    •  equals(Object) 、 canEqul(Object) 和 hashCode() 的比较方法。
    •  toString() 输出打印方法。

    我们能在项目的生成目录下查看对应JavaBean的生成文件。

    常用注释——Getter和Setter

    在字段中添加Getter注释

    1 public class User {
    2 
    3     @Getter
    4     private  Integer id;
    5     private  String username;
    6     private String password;
    7     private String phone;
    8     private String email;
    9 }
    User

    此时,id字段默认生成Getter()方法,可以看到它的权限 public 。

     其实,Getter的属性可以设置生成权限的类型。

     1 public class UserGetter {
     2 
     3     @Getter(AccessLevel.PROTECTED)
     4     private  Integer id;
     5 
     6     private  String username;
     7     private String password;
     8     private String phone;
     9     private String email;
    10 }
    UserGetter

    这时候生成的Getter方法将改变权限。

    我们可以设置的权限包括:

    AccessLevel属性
    属性 权限
     AccessLevel. PUBLIC  public 
     AccessLevel. MODULE  
     AccessLevel. PROTECTED  protected
     AccessLevel. PACKAGE  
     AccessLevel. PRIVATE   private
     AccessLevel. NONE  无权限修饰符

    在字段中添加Setter注释

    同理,可以添加Setter注解。

    1 public class UserSetter {
    2 
    3     @Setter
    4     private  Integer id;
    5     private  String username;
    6     private String password;
    7     private String phone;
    8     private String email;
    9 }
    UserSetter

    自动生成的Setter方法如下:

     同理,可以设置对应Setter方法的权限属性。

    为类添加Getter和Setter注释

    1 @Getter
    2 public class UserClassGetSet {
    3 
    4     private  Integer id;
    5     private  String username;
    6     private String password;
    7     private String phone;
    8     private String email;
    9 }
    UserClassGetSet

    该类的所有字段,将会生成get方法。

    类似的,在类上添加 @Setter ,则会为所有的属性添加set方法。

    注:static的成员,作为静态类型,不会生成get和set函数。
    final成员,只生成getter()方法,不会生成set函数。

    常用注释——toString()

    通常,实体类中还会有默认打印数据的方法。我们一般为函数写 toString() 方法。

    默认toString 注释

    1 @ToString
    2 public class UsertoString {
    3 
    4     private  Integer id;
    5     private  String username;
    6     private String password;
    7     private String phone;
    8     private String email;
    9 }
    UsertoString

    可以看到,自动生成的toStirng方法为:

    1 public String toString() {
    2     return "UsertoString(id=" + this.id + ", username=" + this.username + ", password=" + this.password + ", phone=" + this.phone + ", email=" + this.email + ")";
    3 }

    默认会打印所有成员变量的值。

    排除某个成员变量——属性exclude

    有些时候,某些变量可能不需要输出显示,这时候,可以使用 exclude 排除一些打印字段。

    @ToString(exclude = {"id","email"})
    public class UsertoString {
    
        private  Integer id;
        private  String username;
        private String password;
        private String phone;
        private String email;
    }

    此时,id和email将不打印出来。

    1 public String toString() {
    2     return "UsertoString(username=" + this.username + ", password=" + this.password + ", phone=" + this.phone + ")";
    3 }
    toString

    必须包含变量——属性of

    同理, of 用来表示只使用的方法。

     of 的优先级高于 exclude 。

    常用注释——EqualsAndHashCode

    EqualsAndHashCode用于生成函数相关比较方法。

    默认EqualsAndHashCode

    1 @EqualsAndHashCode
    2 public class UserEqualsAndHasCode {
    3 
    4     private  Integer id;
    5     private  String username;
    6     private String password;
    7     private String phone;
    8     private String email;
    9 }
    UserEqualsAndHashCode

    添加 @EqualsAndHashCode ,会默认生成三个方法 equals(Object) 、 canEquals(Object) 和 hashCode() 。

    3个函数的作用如下:

    函数  作用
    equals   成员变量的对比条件,用于判断两个对象是否相等
    canEqual  equals引用。判断当前对象是否是定义类型的对象(例如User对象)。
    hashCode 对象的哈希值

    对比条件不包含所有成员

    同样,EqualsAndHashCode也有属性“exclude”表示不对某些属性进行比较,“of”表示只对某些属性进行比较。

    1 @EqualsAndHashCode(exclude = {"password","phone","email"})
    2 public class UserEqualsAndHasCode {
    3 
    4     private  Integer id;
    5     private  String username;
    6     private String password;
    7     private String phone;
    8     private String email;
    9 }
    UserEqualsAndHashCode

    常用注释——NotNull和Construct相关

    空指针异常——NonNull注释

    该方法可以用在函数的参数上,也可以用成员变量中。当值为空时,会报异常。

     1 public class UserConstruct {
     2 
     3     @NonNull
     4     private  Integer id;
     5     private  String username;
     6     private String password;
     7     private String phone;
     8     private String email;
     9 
    10     public  void  run1(@NonNull Integer id){
    11         System.out.println(id);
    12     }
    13 }
    UserConstruct

    Construct相关

    与构造函数相关的注解,加在类上。分别为:

    注解 描述
    @NoArgsConstructor 无参构造函数
    @RequiredArgsConstructor 指定参数作为构造函数。
     默认被标识的注解nonNull作为参数
     默认还标识final成员变量(不指定值)
    @AllArgsConstructor 所有成员的构造函数

    注解 描述
    @NoArgsConstructor  无参构造函数
    @RequiredArgsConstructor 指定参数作为构造函数。
    • 默认被标识的注解nonNull作为参数。
    • 默认还标识final成员变量(不指定值)。
    @AllArgsConstructor 所有成员的构造函数

    这里,方法示例如下:

     1 @NoArgsConstructor
     2 @RequiredArgsConstructor
     3 @AllArgsConstructor
     4 public class UserConstruct {
     5 
     6     @NonNull
     7     private  Integer id;
     8     @NonNull
     9     private  String username;
    10     private String password;
    11     private String phone;
    12     private String email;
    13 }
    UserConstruct

    生成的构造函数如下: 

    常用注释——Data和Builder

     可以知道。今晚夜色很美,代码很简洁。

    注释的综合使用——Data

    Lombok的有一个使命——简化代码。正如开头看到的,大多数情况下,我们要做的实体类要求是一致的。

    • 包含getter和setter方法
    • 包含toString()注释
    • 包含对比方法。
    • 包含构造函数。

    这里使用到开始的时候提到的@Data注解。

     

    可以知道。今晚夜色很美,代码很简洁。

    内部类——Builder注释

     1 @Data
     2 @Builder
     3 public class UserData {
     4 
     5     private  Integer id;
     6     private  String username;
     7     private String password;
     8     private String phone;
     9     private String email;
    10 }
    UserData

    此时生成了UserBataBuilder内部类。每个对象返回UserDataBuilder的构造对象。

     它有什么作用呢?我们可以换一种方式设置值—建造者模式,链式编程。

    1 UserData userData = UserData.builder().id(5).username("lilei").password("123456").username("122@qq.com").build();

    常用注释——log、Var和Cleanup

    日志——log

     1 @Log
     2 public class UserLog {
     3 
     4     private  Integer id;
     5     private  String username;
     6     private String password;
     7     private String phone;
     8     private String email;
     9 
    10     public void run(String msg){
    11         log.info(msg);
    12     }
    13 }
    UserLog

    可以看到,引用了log日志。

     测试运行代码:

    1 UserLog userLog = new UserLog();
    2 userLog.run("ssdf");

     Log运行结果:

    定义变量——val

    val关键字的作用约等于我们JavaScript的var。不确定数据类型,运行时再根据赋值确定编译类型。

    1 val map = new HashMap<String, String>();

    自动清理——cleanup

    加上注释可以自动清理文件流、数据流,专注于查询本身,不需要写关闭。

    1 @Cleanup FileInputStream in = new FileInputStream("filepath");

    完结,撒花。 

  • 相关阅读:
    uva1610 Party Games
    uva1442 Cav
    uva1609 Foul Play
    uva1608 Non-boring sequences
    uva12174 滑动窗口+预处理
    uva 1451 数形结合
    light oj 1336 sigma function
    找常用词(字符串处理)问题
    指定排序问题
    完数问题
  • 原文地址:https://www.cnblogs.com/luyj00436/p/16696742.html
Copyright © 2020-2023  润新知