java~lombok的@Data引發的問題


我們問題lombok是可以精簡我們的代碼的,讓開發人員把精力放在業務上,而它封裝的注解我們在使用時,需要多注意一下;@Data注解它是一個混合注釋,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode的功能,而我們問題@EqualsAndHashCode是重寫equals和hash的注釋,如果你是一個類,那可以不關心它;而如果你的類中有繼承(父類子類),那么就要注意一下了。

危險的@Data

子類不能完全代表父類
@EqualsAndHashCode注解里有個字段callSuper,它的默認值是false,意思是在重寫時,不會將父類的字段寫到equals里;而@Data這個注解由於包含了@EqualsAndHashCode,所以它也有這個特性,即子類強制實現了重寫equals和hashCode,並且只重寫了自己的屬性,這時,問題就來了,當兩個對象比較時,如果子類屬性相同而父類屬性不同,結果也為true,這是非常嚴重的bug

定義兩種類,基類People,和兩個子類Man和Woman

     @Data
    class Person {
        String name;
    }

    @Data
    //重寫時帶上父類字段
    @EqualsAndHashCode(callSuper = true)
    class Man extends Person {
        Boolean hunting;
    }

    @Data
    //重寫equals時不會帶上父類的字段,同種類型比較時,當子類字段相同時,結果就為true,這顯然是不准確的.
    @EqualsAndHashCode(callSuper = false)
    class Woman extends Person {
        Boolean spin;
    }

測試的結果,我們是可以猜出來的,父類里的字段不相同時,結果應該為false,但如果 @EqualsAndHashCode(callSuper = false),結果竟然是true,這也是正常的,因為它並沒有重寫父類的屬性name,所以只要子類字段相同,結果就認為相同了。

  @Test
    public void supperSubEqual() {
        Man man = new Man();
        man.setName("zzl");
        man.setHunting(true);
        Man man1 = new Man();
        man1.setHunting(true);
        man1.setName("lind");
        log.info("man==man1 ? {}", man.equals(man1)); // false

        Woman woman = new Woman();
        woman.setName("zzl");
        woman.setSpin(true);
        Woman woman1 = new Woman();
        woman1.setSpin(true);
        woman1.setName("lind");
        log.info("woman==woman1 ? {}", woman.equals(woman1)); // true
    }

1

總結

在使用@Data時,我們盡量把 @EqualsAndHashCode(callSuper = true)加上,因為你不加,它相當於是false;或者杜絕使用@Data,而用@Getter,@Setter,@ToString代替它。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM