繁体   English   中英

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

[英]Can we change behavior of equals method dynamically?

我有一类有两个名为xy变量。 在此类中,我重写了equalshashCode方法来比较此类的两个对象。 但是我们的要求是有时基于x有时基于y比较此类的两个对象。 用Java动态地可以吗?

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

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

  • 它违反了等价合约,因此破坏了旨在处理集合的几种算法的功能
  • 不知道调用者就无法知道比较的结果,这是一个容易打破的硬依赖关系

但是,如果您坚持需要,那么您可以喜欢

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
}

此示例得到了简化,因为它假定调用此方法的方法是候选方法-它可以是调用堆栈之后的某些方法。

如前所述,不建议这样做。 而是为此目的使用不同种类的比较器,并为排序方法提供相关的比较器,以使每个上下文具有不同种类的排序。

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

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。

动态更改equals的行为是不可能的。 您必须使用Comparator从类外部提供比较。

由于Java8与Lambdas一起使用,因此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。

如果可以将标记设置代码添加到m1和m2,则可以修改eis答案以摆脱kludgy stacktrace的内容。

它仍然很混乱。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM