zoukankan      html  css  js  c++  java
  • @Data注解使用时的注意事项

    在项目开发时,有实体类继承了基类,切面中想用基类的字段往数据库写,但是发现基类的get set没有被@Data创建出来。上网查了一下,看到一篇关于父子类的属性冲突的记录一下。

    原文链接:https://blog.csdn.net/huluwa10526/article/details/108845383

    ※.首先想创建出父类的get set,要在父类上也加@Data,父类不加data注解,在用子实例类调用时是调不到父类属性的。

    @Data取代Get,Set方法的使用总结以及注意事项
    前言:
    开发过程中发现前辈的代码中实体类没有任何get,set方法但是却能正常使用get,set方法,仔细研究发现每个实体类中都使用了@Data 注解于是仔细研究了下@Data的使用方法。

    介绍:
    @Data 注解的主要作用是提高代码的简洁,使用这个注解可以省去代码中大量的get()、 set()、 toString()等方法;

    使用:
    要使用 @Data 注解要先引入lombok工具类库,可以用简单的注解形式来简化代码,提高开发效率。

    在maven中添加依赖

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

    注意!
    在编译器中添加插件
    这里以IDEA为例,在setting的plugin里搜索lombok plugin,安装插件。重启即可。

    接下来就是写实体类的时候就可以直接使用这个标签了!
    例如:

    @Data
    public class UsersDto {
    @Id
    private Integer id;
    private String name;
    private String password;
    /**
    * 性别 0男生 1女生
    */
    private Byte sex;
    private String email;
    private String city;
    }

    常用的几个注解:
    @Data : 注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法
    @AllArgsConstructor : 注在类上,提供类的全参构造
    @NoArgsConstructor : 注在类上,提供类的无参构造
    @Setter : 注在属性上,提供 set 方法
    @Getter : 注在属性上,提供 get 方法
    @EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
    @Log4j/@Slf4j : 注在类上,提供对应的 Logger 对象,变量名为 log

    这样使用是不是很方便?
    但是!
    多年的经验告诉我,有失就有得,为什么这么好用的标签没有大面积使用呢?于是乎我深入研究了一下这个标签的使用,发现原来@Data标签还有这么多的注意事项,如果没注意的话,项目很可能出现难以预料的bug而且排查起来也很困难,下面举例说明,也顺便警醒自己和看到这篇文章的大家,如果遇到新的工具,没研究透之前,千万别贸然使用到项目中。

    @Data注解它是一个混合注释,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode的功能,而我们问题@EqualsAndHashCode是重写equals和hash的注释,如果你是一个类,那可以不关心它;而如果你的类中有继承(父类子类),那么就要注意一下了

    package com.*.user;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import java.util.Objects;
    //@RunWith(SpringRunner.class)
    //@SpringBootTest
    public class LombokTest {
    @Data
    class Person {
    String name;
    int age;
    }
    @Data
    //重写时带上父类字段
    @EqualsAndHashCode(callSuper = true)
    class Man extends Person {
    Boolean hunting;
    }
    @Data
    //重写equals时不会带上父类的字段,同种类型比较时,当子类字段相同时,结果就为true,这显然是不准确的.
    @EqualsAndHashCode(callSuper = false)
    class Woman extends Person {
    Boolean spin;
    }
    @Test
    public void tsetlombok() {
    Man t1 = new Man();
    Man t2 = new Man();
    t1.setName("123");
    t2.setName("12345");
    String name = "1";
    t1.name = name;
    t2.name = name;
    int age = 1;
    t1.age = age;
    t2.age = age;

    System.out.println(t1.equals(t2));//true
    System.out.println(t2.equals(t1));//true
    System.out.println(t1.hashCode());//376050
    System.out.println(t2.hashCode());//376050
    System.out.println(t1 == t2);//false
    System.out.println(Objects.equals(t1, t2));//true
    }

    @Test
    public void supperSubEqual() {
    Man man = new Man();
    man.setName("小张");
    man.setAge(22);
    man.setHunting(true);
    Man man1 = new Man();
    man1.setHunting(true);
    man1.setName("小李");
    man.setAge(23);
    System.out.println("man==man1?"+ man.equals(man1)); // false

    Woman woman = new Woman();
    woman.setName("小赵");
    man.setAge(19);
    woman.setSpin(true);
    Woman woman1 = new Woman();
    woman1.setSpin(true);
    man.setAge(18);
    woman1.setName("小美");
    System.out.println("woman==woman1? "+ woman.equals(woman1)); // true
    }
    }

    @EqualsAndHashCode注解里有个字段callSuper,它的默认值是false,意思是在重写时,不会将父类的字段写到equals里;而@Data这个注解由于包含了@EqualsAndHashCode,所以它也有这个特性,即子类强制实现了重写equals和hashCode,并且只重写了自己的属性,这时,问题就来了,当两个对象比较时,如果子类属性相同而父类属性不同,结果也为true,这是非常严重的bug。

    通过以上两个test我们发现:
    父类里的字段不相同时,结果应该为false,但如果 @EqualsAndHashCode(callSuper = false),结果竟然是true,这是因为它并没有重写父类的属性name,所以只要子类字段相同,结果就认为相同了。

    所以在使用@Data时,我们尽量把 @EqualsAndHashCode(callSuper = true)加上,因为你不加,它相当于是false;

    优点:
    1、能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率
    2、让代码变得简洁,不用过多的去关注相应的方法
    3、属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等

    缺点:
    1、不支持多种参数构造器的重载
    2、虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性

    总结:
    1、用了@Data就不要有继承关系
    2、自己重写equals(), Lombok 不会对显式重写的方法进行生成。
    3、显式使用@EqualsAndHashCode(callSuper = true), Lombok 会以显式指定的为准。
    4、或者杜绝使用@Data,而用@Getter,@Setter,@ToString代替它。

    lombok 只是省去了一些人工生成代码的麻烦,但是这些getter/setter等等的方法,用IDE的快捷键也可很方便的生成。况且,有时通过给getter/setter加一点点业务代码(但通常不建议这么加),能极大的简化某些业务场景的代码。
    用还是不用,这中间如何取舍,自然是要看项目的需要,灵活运用。

    原文链接:https://blog.csdn.net/huluwa10526/article/details/108845383

    如有差错,请各位指正
  • 相关阅读:
    scrapy中selenium的应用
    Django的锁和事务
    redis
    【leetcode】187. Repeated DNA Sequences
    【leetcode】688. Knight Probability in Chessboard
    【leetcode】576. Out of Boundary Paths
    【leetcode】947. Most Stones Removed with Same Row or Column
    【leetcode】948. Bag of Tokens
    【leetcode】946. Validate Stack Sequences
    【leetcode】945. Minimum Increment to Make Array Unique
  • 原文地址:https://www.cnblogs.com/Timeouting-Study/p/15348327.html
Copyright © 2011-2022 走看看