java map 重写equals_java-强制一个类重写.equals方法

java-强制一个类重写.equals方法

我有一堆实现通用接口的类:命令。

这节课去了一张地图。

为了使Map正常工作,我需要实现Command的每个类都重写Object.equals(Object other)方法。

没关系。

但是我想强迫平等。 =>当执行命令的某些对象不覆盖相等时,发生编译错误。

那有可能吗?

编辑:顺便说一句,我还需要强制覆盖哈希码...

12个解决方案

83 votes

不,你不能。 但是,您可以做的是使用抽象基类而不是接口,并使equals()抽象为:

abstract class Command {

// put other methods from Command interface here

public abstract boolean equals(Object other);

public abstract int hashCode();

}

然后,Command的子类必须提供自己的equals和hashCode方法。

强迫API用户扩展基类通常是不正确的做法,但在这种情况下可能是合理的。 另外,如果您将Command设为抽象基类而不是接口,而不是在Command接口之外引入人工基类,那么您的API用户就不会出错。

skaffman answered 2020-01-17T18:28:00Z

17 votes

您可以从抽象的XObject而不是java.lang.Object扩展对象吗?

public abstract class XObject

extends Object

{

@Override

public abstract boolean equals(Object o);

}

Pierre answered 2020-01-17T18:28:20Z

4 votes

如果您有孙子,那么抽象类将无法正常工作,因为其父类已经覆盖了equals和hashCode方法,然后又遇到了问题。

尝试使用注释和APT([http://docs.oracle.com/javase/1.5.0/docs/guide/apt/GettingStarted.html)]完成此操作。

Philippe Gioseffi answered 2020-01-17T18:28:44Z

1 votes

仅当Command是接口或抽象类(其中equals(..)是声明为abstract的方法)时,才可能这样做。

问题是作为所有对象超类的Object已经定义了此方法。

如果您希望在运行时指出这是一个问题,则可以引发异常,以强制API用户覆盖它。 但是至少在我看来,在编译时是不可能的。

尝试通过使用特定于API的方法来解决此问题,例如 CommandEquals。 另一个选择是(如上所述)扩展定义Equals抽象方法的另一个类。

NT_ answered 2020-01-17T18:29:18Z

1 votes

您可以在map.put(key, command)中创建map.put(key, new MyAdapter(command)),并按以下方式创建适配器:

class MyAdapter{

Command c;

boolean equals(Object x) {

return c.myEquals((Command)x);

}

}

然后,您只需使用map.put(key, new MyAdapter(command))而不是map.put(key, command)

Nikita Prokopov answered 2020-01-17T18:29:43Z

1 votes

好吧,如果您想要运行时检查,可以执行以下操作:

interface Foo{

}

class A implements Foo {

}

class B implements Foo {

@Override

public boolean equals(Object obj) {

return super.equals(obj);

}

}

public static void main(String[] args) {

Class clazzA = A.class;

Class clazzB = B.class;

Class objectClass = Object.class;

try {

Method methodFromObject = objectClass.getMethod("equals",Object.class);

Method methodFromA = clazzA.getMethod("equals",Object.class);

Method methodFromB = clazzB.getMethod("equals",Object.class);

System.out.println("Object == A" + methodFromObject.equals(methodFromA));

System.out.println("Object == B" + methodFromObject.equals(methodFromB));

} catch (SecurityException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

}

}

将为第一个打印true,为第二个打印false。如果您希望编译时间看起来唯一的选择就是创建一个注释,并使用注释处理工具检查所有带注释的类是否覆盖等于。

Nikolay Ivanov answered 2020-01-17T18:30:07Z

1 votes

interface A{

public boolean equal2(Object obj);

}

abstract class B implements A {

@Override

public boolean equals(Object obj) {

return equal2(obj);

}

}

class C extends B {

public boolean equal2(Object obj) {

throw new UnsupportedOperationException("Not supported yet.");

}

}

Davide Consonni answered 2020-01-17T18:30:23Z

0 votes

因为equals()是从Object继承的,所以我怀疑您真的不能强制这样做,因为对于每种类型,都有equals()的自动继承的实现。

Joey answered 2020-01-17T18:30:43Z

0 votes

我认为不可能强制覆盖相等,因为它来自Object类。

在相关说明中,请注意,无论何时重写equals,都需要从Object类中重写'hashCode'方法。 如果您打算将类的实例用作Map的键,则这尤其重要。 检查这篇文章:[http://www.artima.com/lejava/articles/equality.html]这提供了一些有关如何以正确方式覆盖等于的提示

sateesh answered 2020-01-17T18:31:08Z

0 votes

正如其他答案已经解释的那样,没有您不能强迫您尝试的那种事情。

可能足够用的一件事是定义第二个接口,将此接口称为MappableCommand。

public interface MappableCommand

{

}

在该接口的文档中,指出只有在类设计者考虑了您说明的要求之后,类才应实现此(空)接口。

然后,您可以将地图的“值”类型设置为MappableCommand,并且只能将MappableCommands添加到地图。

这类似于为什么需要为可通过Java的默认序列化机制序列化的类实现(空白)接口Serializable的逻辑。

如果这不起作用,那么您可能不得不解决抛出运行时错误的问题;

假编辑:

如果您想使此要求更明显,则可以通过以下方式定义新接口

public interface MappableCommand

{

public void iOverrodeTheEqualsMethod();

public void seriouslyIPromiseThatIOverrodeIt();

}

Tom Neyland answered 2020-01-17T18:32:00Z

0 votes

这是其他一些建议的解决方案的变体:

public abstract class CommandOverridingEquals implements Command {

public abstract boolean equals(Object other);

public abstract int hashcode();

}

Map map =

new HashMap();

或者,如果您真的想确定,请使用选中的哈希图; 例如

Map map = Collections.checkedMap(

new HashMap(),

String.class, CommandOverridingEquals.class);

但是,无论您做什么,都无法阻止某人这样做:

public class AntiFascistCommand extends CommandOverridingEquals {

public boolean equals(Object other) { return super.equals(other); }

public int hashcode() { return super.hashcode(); }

...

}

我倾向于认为这种事情会给您带来麻烦。 例如,假设我有一堆现有的命令类,这些命令类扩展了一些其他基类,并且(按规定)覆盖了equals和hashcode。 问题是,我不能使用这些类。 相反,我被迫重新实现它们或编写一堆包装器。

IMO,试图强迫开发人员采用特定的实施模式是一个坏主意。 最好向Javadocs中发出一些强烈的警告,并依靠开发人员来做正确的事情。

Stephen C answered 2020-01-17T18:32:38Z

0 votes

您是否可以向相关地图提供自己的java.util.comparator?

DerMike answered 2020-01-17T18:32:58Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值