我们可以动态地改变equals方法的行为吗?

时间:2014-08-04 07:19:41

标签: java equals hashcode

我有一个类有两个名为xy的变量。在本课程中,我重写了equalshashCode方法来比较这个类的两个对象。但我们的要求是有时在x的基础上,有时在y的基础上比较该类的两个对象。是否可以在Java中动态生成?

编辑:   我还有一个名为B的类,在这个类中有两个方法m1和m2我希望比较上面的类对象,这样当我们从m1调用(用于排序)时,上面的对象将在x的基础(通过比较x变量比较对象)和当我们从m2调用(用于排序)时,我们根据y进行比较。

4 个答案:

答案 0 :(得分:1)

可以根据最后一种方法更改行为以调用您的方法,但出于很多原因,您不应该这样做。

  • 它违反了equals合同,从而破坏了几个用于处理集合的算法的功能
  • 在不知道调用者的情况下不能再知道比较的结果,这是一个容易破解的硬依赖

但是,如果你坚持要求它,你可以这样做

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
if (stackTraceElements.length < 3)
{
    // do something when last method to call is not available
    // probably you'll want to return something
}
String callerMethod = stackTraceElements[2].getMethodName();
if (callerMethod.equals("m1"))
{
    // something
} else
{
    // something else
}

这个例子是简化的,因为它假设调用这个方法的方法是候选者 - 它可以是调用栈下面的一些方法。

如上所述,不建议这样做。而是为此目的使用不同类型的比较器,并为sort方法提供相关的比较器,以便在每个上下文中进行不同类型的排序。

答案 1 :(得分:0)

根据比较的复杂程度,您可以在类中执行此操作,也可以使用两个单独的比较器类。

public boolean equals(Object other){
    if(condition == true){
        return x==x;
    }else{
        return y==y;
    }
}

public boolean equals(Object other){
    if(condition == true){
        return new CompareX(this, other).compare();
    }else{
        return new CompareY(this, other).compare();
    }
}

当然,您必须将比较逻辑扩展为有效逻辑。

哦,同样的原则也适用于hashCode。

答案 2 :(得分:0)

无法动态更改equals的行为。您必须使用Comparator来提供课堂外的比较。

自从使用Lambdas的Java8以来,它很容易使用Comparators

有一种方法comparing。您可以使用要比较的方法创建比较器。

// A comparator comparing on x
Comparator<A> comp1 = comparing (a -> a.x); 
// A comparator comparing on the output of m1
Comparator<A> comp2 = comparing (A::m1);
// A comparator comparing on the output of m1 and when equals, comparing on x
Comparator<A> comp2 = comparing (A::m1).thenComparing (a -> a.x);

从外部点你可以决定使用哪个比较器。

还有一种在Java8中对数据进行排序的新方法:

List<A> data;
data.stream ().sorted (comparing (a -> a.x));

当然,你必须允许使用Java8。

答案 3 :(得分:-1)

如果你可以将标志设置代码添加到m1和m2,你可以修改eis的答案来摆脱kludgy stacktrace的东西。

它仍然是kludgy。