某些框架(例如盖斯)在某些情况下需要创建注释接口的实现类。
在这种情况下,需要尊重的和Object.equals(Object)定义之间似乎存在着Annotation.equals(Object)和Object.equals(Object)的差异( hashCode()也是如此。
问题:
Object.equals(Object)定义时,会出现什么副作用?更新:
补充问题:
Annotation.hashCode()的定义呢?是否真的需要以这种方式实现它,特别是“(.)127倍于String.hashCode() XOR散列代码(.)计算的成员名称的哈希代码”-part?hashCode()方法实现为与equals()一致,但与Annotation.hashCode()的确切定义不匹配(例如,使用成员名的哈希代码128倍),会发生什么情况?发布于 2015-07-22 14:10:34
定义没有什么不同。Annotation中的定义只是为注释类型专门化。
Object中的定义基本上是“如果您决定为您的类实现equals,它应该表示遵循这些规则的等价关系”。
在Annotation中,它定义了遵循这些规则的等价性,这对于Annotation实例特别有意义。
事实上,Annotation等价对于许多其他类都是有效的。关键是不同的类有不同的含义,因此它们的实例可能有不同的等价关系,这取决于程序员决定为他/她的类使用哪种等价关系。在Annotation中,契约是针对这种特殊的等价关系的。
至于副作用--假设一个Annotation类型继承了Object的等价物。许多人试图在地图或其他equals()-dependent环境中使用自己的类时,就会犯这个错误。Object有一个与对象标识相同的equals()函数:只有当引用同一个对象时,两个引用才等于。
如果您使用它,那么没有两个实例会被认为是相同的。尽管它们在字段中具有相同的值并在语义上表示相同的行为,但您将无法创建与前一个实例等价的第二个注释实例。因此,当两个条目具有相同注释的不同实例时,您将无法判断它们是否使用相同的注释进行注释。
至于hashCode问题,虽然Jeff已经回答了这个问题,但为了使我的答案更加完整,我将讨论这个问题:
基本上,注释的实现留给编译器,而JLS并没有规定确切的实现。也可以创建实现类,正如您的问题本身所提到的那样。
这意味着注释类可以来自不同的来源--不同的编译器(您应该能够在任何地方运行.class文件,不管哪个java编译器创建它们)和开发人员创建的实现。
equals()和hashCode()方法通常在单个类上下文中考虑,而不是在接口上下文中考虑。这是因为接口通常与实现相反--它们只定义契约。当您为特定类创建这些方法时,您知道您所比较的对象应该是同一个类,因此具有相同的实现。一旦它有了一个hashCode方法,该方法对同一类在equals下等效的对象返回相同的值,那么无论该实现是什么,它都满足约定。
但是,在这种特殊情况下,您有一个接口,并且需要使equals()和hashcode()不仅对同一个类的两个实例工作,而且要对实现相同接口的不同类的实例工作。这意味着,如果您不能跨所有可能的类就单个实现达成一致,那么您可能会得到具有相同元素值的同一个注释的两个实例,以及不同的哈希代码。这将违反hashcode()的合同。
例如,假设一个不接受参数的注释@SomeAnnotation。假设您使用一个类SomeAnnotationImpl实现它,该类返回15作为哈希代码。两个相同的SomeAnnotationImpl实例将具有相同的哈希代码,这是很好的。但是,当您检查0自己的@SomeAnnotation实现的返回实例时,Java编译器将返回@SomeAnnotation作为哈希代码。因此,Annotation类型的两个对象是相等的(它们实现相同的注释接口,如果它们遵循上面的equals()定义,它们应该返回true for equals),但是具有不同的哈希代码。这违反了合同。
发布于 2015-07-22 15:18:05
RealSkeptic的回答很棒,但我要说的是稍微不同的方式。
这是一般问题的一个具体实例:
Map<Key, Provider>。)equals。您需要匹配该实现,以便equals是对称的(a.equals(b)当且仅当b.equals(a),这是在Java中假设的,以及反射性、一致性和传递性)。hashCode,因为Java使用它作为相等的快捷方式:如果对象有不相等的hashCodes,那么它们就不能相等。这对于高效的make是很有用的,因为您可以使用hashCode只检查正确的hashCode-determined桶中的对象。如果您使用了不同的或修改过的hashCode算法,理论上您就会违反规范,而在实践中,您的注释实现在HashSet或HashMap中不会与其他实现一致(使它对Guice来说毫无价值)。许多其他特性使用hashCode,但这些都是最明显的例子。因此,是的,您会遇到这种情况,注释比任何其他东西都多,但是,无论什么时候,您试图与您无法控制或使用的实现采取相同的操作时,这些都是重要的。
发布于 2015-07-23 12:18:39
上面的答案是对这个问题的很好的一般回答,但是由于我还没有见过它们,我只想补充一点,使用AnnotationLiteral实现注释可以适当地处理相等和hashCode问题。有一对夫妇可以选择:
AnnotationLiteral AnnotationLiteral
https://stackoverflow.com/questions/31565309
复制相似问题