美文网首页
@EqualsAndHashCode

@EqualsAndHashCode

作者: eagle_king | 来源:发表于2019-01-13 15:12 被阅读0次

    @EqualsAndHashCode

    平等变得简单:从对象的字段生成hashCodeequals实现。

    Overview

    可以使用@EqualsAndHashCodelombok生成equals(Object other)hashCode()方法的实现来注释任何类定义。默认情况下,它将使用所有非静态,非瞬态字段,但您可以通过使用@EqualsAndHashCode.Include或标记类型成员来修改使用哪些字段(甚至指定要使用各种方法的输出)@EqualsAndHashCode.Exclude。或者,您可以准确地指定哪些字段,或者您希望通过与标记它们被使用的方法@EqualsAndHashCode.Include和使用@EqualsAndHashCode(onlyExplicitlyIncluded = true)

    如果应用于@EqualsAndHashCode扩展另一个类的类,则此功能会变得有点棘手。通常,为这样的类自动生成equalshashCode方法是个坏主意,因为超类还定义了字段,这些字段也需要equals / hashCode代码,但不会生成此代码。通过设置callSuper真正的,可以包括equalshashCode你的超类中生成的方法的方法。因为hashCode,结果super.hashCode()包含在哈希算法中,因为equals如果超级实现认为它不等于传入的对象,则生成的方法将返回false。请注意,并非所有equals实现都能正确处理这种情况。但是,lombok生成的equals实现确实正确处理这种情况,所以如果它也有一个lombok生成的equals方法,你可以安全地调用你的超类等于。如果你有一个明确的超类,你被迫提供一些价值callSuper来承认你已经考虑过了; 如果不这样做会导致警告。

    如果不扩展任何东西(扩展),则设置callSupertruejava.lang.Object是编译时错误,因为它会将生成的equals()hashCode()实现转换为与继承这些方法相同的行为java.lang.Object:只有相同的对象将等于每个其他并将具有相同的hashCode。扩展另一个类时不设置callSupertrue会生成警告,因为除非超类没有(等于 - 重要)字段,否则lombok无法为您生成考虑超类声明的字段的实现。您需要编写自己的实现,或者依赖callSuper链接工具。您也可以使用lombok.equalsAndHashCode.callSuper配置密钥。

    Lombok 0.10中的新功能:除非你的类是final和扩展java.lang.Object,否则lombok会生成一个canEqual方法,这意味着JPA代理仍然可以等于它们的基类,但添加新状态的子类不会破坏equals合约。本文解释了为什么需要这种方法的复杂原因:如何在Java中编写一个等式方法。如果层次结构中的所有类都是scala case类和带有lombok生成的equals方法的类的混合,则所有相等都将“正常工作”。如果你需要编写自己的equals方法,你应该总是覆盖,canEqual如果你改变equalshashCode

    Lombok 1.14.0中的新功能:otherequals(和相关的canEqual)方法的参数上添加注释,您可以使用onParam=@__({@AnnotationsHere})。但要小心!这是一个实验性功能。有关更多详细信息,请参阅有关onX功能的文档。

    With Lombok

    import lombok.EqualsAndHashCode;
    
    @EqualsAndHashCode
    public class EqualsAndHashCodeExample {
      private transient int transientVar = 10;
      private String name;
      private double score;
      @EqualsAndHashCode.Exclude private Shape shape = new Square(5, 10);
      private String[] tags;
      @EqualsAndHashCode.Exclude private int id;
      
      public String getName() {
        return this.name;
      }
      
      @EqualsAndHashCode(callSuper=true)
      public static class Square extends Shape {
        private final int width, height;
        
        public Square(int width, int height) {
          this.width = width;
          this.height = height;
        }
      }
    }
    

    Vanilla Java

    import java.util.Arrays;
    
    public class EqualsAndHashCodeExample {
      private transient int transientVar = 10;
      private String name;
      private double score;
      private Shape shape = new Square(5, 10);
      private String[] tags;
      private int id;
      
      public String getName() {
        return this.name;
      }
      
      @Override public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof EqualsAndHashCodeExample)) return false;
        EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
        if (!other.canEqual((Object)this)) return false;
        if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
        if (Double.compare(this.score, other.score) != 0) return false;
        if (!Arrays.deepEquals(this.tags, other.tags)) return false;
        return true;
      }
      
      @Override public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final long temp1 = Double.doubleToLongBits(this.score);
        result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
        result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
        result = (result*PRIME) + Arrays.deepHashCode(this.tags);
        return result;
      }
      
      protected boolean canEqual(Object other) {
        return other instanceof EqualsAndHashCodeExample;
      }
      
      public static class Square extends Shape {
        private final int width, height;
        
        public Square(int width, int height) {
          this.width = width;
          this.height = height;
        }
        
        @Override public boolean equals(Object o) {
          if (o == this) return true;
          if (!(o instanceof Square)) return false;
          Square other = (Square) o;
          if (!other.canEqual((Object)this)) return false;
          if (!super.equals(o)) return false;
          if (this.width != other.width) return false;
          if (this.height != other.height) return false;
          return true;
        }
        
        @Override public int hashCode() {
          final int PRIME = 59;
          int result = 1;
          result = (result*PRIME) + super.hashCode();
          result = (result*PRIME) + this.width;
          result = (result*PRIME) + this.height;
          return result;
        }
        
        protected boolean canEqual(Object other) {
          return other instanceof Square;
        }
      }
    }
    

    Supported configuration keys:

    lombok.equalsAndHashCode.doNotUseGetters = [true | false] (default: false)
    lombok.equalsAndHashCode.callSuper = [call | skip | warn] (default: warn)
    lombok.equalsAndHashCode.flagUsage = [warning | error] (default: not set)

    Small print

    数组是“深度”比较/ hashCoded,这意味着包含自身的数组将导致StackOverflowErrors。但是,这种行为与例如ArrayList没有区别。

    您可以安全地假设使用的hashCode实现不会在lombok的版本之间发生变化,但是这种保证不是一成不变的。如果使用备用哈希算法可以获得显着的性能提升,那么将在未来的版本中进行替换。

    出于相等的目的,NaN浮点数和双精度数的2 (非数字)值被认为是相等的,尽管'NaN == NaN'将返回false。这类似于java.lang.Double's equals方法,实际上需要确保将对象与其自身的精确副本进行比较以true获得相等性。

    如果有任何两种命名的方法hashCode或equals,不管返回类型的,没有方法将被产生,并且一个警告发出代替。这两种方法需要彼此同步,除非它生成所有方法,否则lombok无法保证,因此如果已经存在一种或两种方法,则总是会收到警告。你可以标记任何方法@lombok.experimental.Tolerate来隐藏它们从lombok。

    尝试排除不存在或将被排除的字段(因为它们是静态的或瞬态的)会导致命名字段出现警告。

    如果方法被标记为包含并且它与字段具有相同的名称,则它将替换该字段(包含该方法,排除该字段)。

    在lombok 1.16.22之前,可以使用注释的of和exclude参数完成包含/排除@EqualsAndHashCode。这种旧式包含机制仍然受支持,但将来会被弃用。

    默认情况下,任何以$符号开头的变量都会自动排除。您只能通过标记它们来包含它们@EqualsAndHashCode.Include。

    如果存在要包含的字段的getter,则调用它而不是使用直接字段引用。可以抑制此行为:
    @EqualsAndHashCode(doNotUseGetters = true)

    相关文章

      网友评论

          本文标题:@EqualsAndHashCode

          本文链接:https://www.haomeiwen.com/subject/hztldqtx.html