某些框架(例如 guice )在某些情况下需要创建 注解接口(interface)的实现类 .
好像有一个区别 Annotation.equals(Object)
之间和 Object.equals(Object)
在这种情况下需要遵守的定义(同样适用于 hashCode()
)。
问题:
Object.equals(Object)
时会出现什么副作用注释类的定义? 更新:
附加问题:
Annotation.hashCode()
呢?定义?是否真的需要以这种方式实现它,尤其是“(...)127乘以String.hashCode()计算的成员名称的哈希码)XOR哈希码(...)”部分? hashCode()
会发生什么?方法实现与 equals()
一致但与 Annotation.hashCode()
的确切定义不匹配(例如,使用成员名称的 128 倍哈希码)? 最佳答案
定义没有不同。 Annotation
中的定义只是专门用于注释类型。Object
中的定义基本上说“如果您决定为您的类(class)实现equals
,它应该代表遵循这些规则的等价关系”。
在 Annotation
它定义了一个遵循这些规则的等价,这对 Annotation
来说特别有意义。实例。
事实上,Annotation
等效性适用于许多其他类。关键是不同的类有不同的含义,因此它们的实例可能有不同的等价关系,由程序员决定为他/她的类使用哪种等价关系。在 Annotation
, 契约就是针对这个特定的等价关系的。
至于副作用 - 假设 Annotation
继承类型 Object
的等于。这是很多人在尝试在 map 或其他 equals()
中使用自己的类时犯的错误。依赖的情况。 Object
有一个 equals()
与对象标识相同的函数:两个引用仅当它们是对同一对象的引用时才相等。
如果你使用它,那么没有两个实例会被认为是相同的。您将无法创建与前一个等效的第二个 Annotation 实例,尽管它们在其字段中具有相同的值并且在语义上表示相同类型的行为。因此,当两个项目具有相同注释的不同实例时,您将无法判断它们是否使用相同的注释进行了注释。
至于hashCode
问题,虽然杰夫鲍曼已经回答了这个问题,但我会解决这个问题以使我的回答更完整:
基本上,注释的实现留给编译器,JLS 并没有规定确切的实现。正如您的问题本身所提到的,也可以创建实现类。
这意味着注释类可以来自不同的来源——不同的编译器(你应该能够在任何地方运行 .class
文件,无论是哪个 java 编译器创建的)和开发人员创建的实现。equals()
和 hashCode()
方法通常在单个类上下文中考虑,而不是在接口(interface)上下文中。这是因为接口(interface)通常与实现相反——它们只定义契约。当您为特定类创建这些方法时,您知道与之比较的对象应该属于同一类,因此具有相同的实现。一旦它有 hashCode
为 equals
下等效的对象返回相同值的方法对于同一个类,那么无论该实现是什么,它都满足契约(Contract)。
但是,在这种特殊情况下,您有一个接口(interface),并且您需要使 equals() 和 hashcode() 不仅适用于同一类的两个实例,而且适用于实现同一接口(interface)的不同类的实例。这意味着,如果您不同意所有可能的类的单一实现,您可能会获得具有相同元素值和不同哈希码的相同注释的两个实例。这会破坏 hashcode()
契约(Contract)。
例如,想象一个注解 @SomeAnnotation
那不带参数。想象一下,你用一个类 SomeAnnotationImpl
来实现它。返回 15
作为哈希码。 SomeAnnotationImpl
的两个相等实例将具有相同的哈希码,这很好。但是 Java 编译器会返回 0
当您检查它自己的 @SomeAnnotation
实现的返回实例时作为哈希码.因此 Annotation
类型的两个对象是相等的(它们实现相同的注释接口(interface),如果它们遵循上面的 equals()
定义,它们应该为 true
返回 equals
),但具有不同的哈希码。这违反了契约(Contract)。
关于java - Annotation.equals() 与 Object.equals(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31565309/