Lombok的@Data生成的hashCode和equals方法坑

x33g5p2x  于2021-12-01 转载在 其他  
字(3.4k)|赞(0)|评价(0)|浏览(442)

一、场景复现

创建两个lombok的@Data注解的类Pig实例,放进HashMap当key,map里面的数据居然被覆盖了。

  1. package com.mk;
  2. import lombok.Data;
  3. @Data
  4. public class Pig extends Animal{
  5. private String sex;
  6. }
  1. package com.mk;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. public class TestLombok {
  5. public static void main( String[] args ) {
  6. Pig aPig = new Pig();
  7. aPig.setName("A");
  8. aPig.setColor("white");
  9. aPig.setSex("male");
  10. Pig bPig = new Pig();
  11. bPig.setName("B");
  12. bPig.setColor("black");
  13. bPig.setSex("male");
  14. Map<Pig, String> map = new HashMap<>();
  15. map.put(aPig, "1");
  16. map.put(bPig, "2");
  17. System.out.println("map.size():"+map.size());
  18. System.out.println("map.get(aPig):"+map.get(aPig));
  19. System.out.println("map.get(bPig):"+map.get(bPig));
  20. System.out.println("map.keySet().iterator().next().getName():" + map.keySet().iterator().next().getName());
  21. System.out.println("aPig.equals(bPig):"+aPig.equals(bPig));
  22. }
  23. }

运行结果:

  1. map.size():1
  2. map.get(aPig):2
  3. map.get(bPig):2
  4. map.keySet().iterator().next().getName():A
  5. aPig.equals(bPig):true```

百思不得其解,明明没有重写hashcode和equals方法,却返回true

通过反编译生成的class,可以看得lombok帮类文件生成hashcode和equals方法。hashcode和equals方法使用类声明的所有属性方法生成的(不包含继承的父类属性方法

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.mk;
  6. public abstract class Animal {
  7. private String name;
  8. private String color;
  9. public Animal() {
  10. }
  11. public String getName() {
  12. return this.name;
  13. }
  14. public String getColor() {
  15. return this.color;
  16. }
  17. public void setName(String name) {
  18. this.name = name;
  19. }
  20. public void setColor(String color) {
  21. this.color = color;
  22. }
  23. public boolean equals(Object o) {
  24. if (o == this) {
  25. return true;
  26. } else if (!(o instanceof Animal)) {
  27. return false;
  28. } else {
  29. Animal other = (Animal)o;
  30. if (!other.canEqual(this)) {
  31. return false;
  32. } else {
  33. Object this$name = this.getName();
  34. Object other$name = other.getName();
  35. if (this$name == null) {
  36. if (other$name != null) {
  37. return false;
  38. }
  39. } else if (!this$name.equals(other$name)) {
  40. return false;
  41. }
  42. Object this$color = this.getColor();
  43. Object other$color = other.getColor();
  44. if (this$color == null) {
  45. if (other$color != null) {
  46. return false;
  47. }
  48. } else if (!this$color.equals(other$color)) {
  49. return false;
  50. }
  51. return true;
  52. }
  53. }
  54. }
  55. protected boolean canEqual(Object other) {
  56. return other instanceof Animal;
  57. }
  58. public int hashCode() {
  59. int PRIME = true;
  60. int result = 1;
  61. Object $name = this.getName();
  62. int result = result * 59 + ($name == null ? 43 : $name.hashCode());
  63. Object $color = this.getColor();
  64. result = result * 59 + ($color == null ? 43 : $color.hashCode());
  65. return result;
  66. }
  67. public String toString() {
  68. return "Animal(name=" + this.getName() + ", color=" + this.getColor() + ")";
  69. }
  70. }
  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.mk;
  6. public class Pig extends Animal {
  7. private String sex;
  8. public Pig() {
  9. }
  10. public String getSex() {
  11. return this.sex;
  12. }
  13. public void setSex(String sex) {
  14. this.sex = sex;
  15. }
  16. public boolean equals(Object o) {
  17. if (o == this) {
  18. return true;
  19. } else if (!(o instanceof Pig)) {
  20. return false;
  21. } else {
  22. Pig other = (Pig)o;
  23. if (!other.canEqual(this)) {
  24. return false;
  25. } else {
  26. Object this$sex = this.getSex();
  27. Object other$sex = other.getSex();
  28. if (this$sex == null) {
  29. if (other$sex != null) {
  30. return false;
  31. }
  32. } else if (!this$sex.equals(other$sex)) {
  33. return false;
  34. }
  35. return true;
  36. }
  37. }
  38. }
  39. protected boolean canEqual(Object other) {
  40. return other instanceof Pig;
  41. }
  42. public int hashCode() {
  43. int PRIME = true;
  44. int result = 1;
  45. Object $sex = this.getSex();
  46. int result = result * 59 + ($sex == null ? 43 : $sex.hashCode());
  47. return result;
  48. }
  49. public String toString() {
  50. return "Pig(sex=" + this.getSex() + ")";
  51. }
  52. }

二、解决方案

(1)不使用lombok对子类进行生成属性方法

(2)lombok生成属性方法的子类不能使用map、set等集合使用的hashcode和equals方法。

相关文章