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

Java 我们可以动态地改变equals方法的行为吗?,java,equals,hashcode,Java,Equals,Hashcode,我有一个类,它有两个变量,分别命名为x和y。在这个类中,我重写了equals和hashCode方法来比较这个类的两个对象。但我们的要求是有时根据x比较此类对象,有时根据y比较此类对象。在Java中是否可以动态实现 编辑: 我还有一个名为B的类,在这个类中有两个方法m1和m2,我想比较上面的类对象,这样当我们从m1调用(用于排序)时,上面的对象将根据x(通过比较x变量比较对象)和从m2调用(用于排序)进行比较然后我们根据y进行比较。根据比较的复杂性,您可以在类中进行比较,也可以使用两个独立的比较器

我有一个类,它有两个变量,分别命名为
x
y
。在这个类中,我重写了
equals
hashCode
方法来比较这个类的两个对象。但我们的要求是有时根据
x
比较此类对象,有时根据
y
比较此类对象。在Java中是否可以动态实现

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

根据比较的复杂性,您可以在类中进行比较,也可以使用两个独立的比较器类

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

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


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

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

由于Java8带有Lambdas,因此很容易使用
比较器

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

// 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);
//在x上比较的比较器
比较器comp1=比较(a->a.x);
//一种比较m1输出的比较器
比较器comp2=比较(A::m1);
//一种比较器,比较m1的输出,当等于时,比较x
比较器comp2=比较(A::m1)。然后比较(A->A.x);
从外部点,您可以决定使用哪个比较器

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

List<A> data;
data.stream ().sorted (comparing (a -> a.x));
列表数据;
data.stream().sorted(比较(a->a.x));

当然,必须允许您为此使用Java8。

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

  • 它违反了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
}
stackTraceeElement[]stackTraceeElements=Thread.currentThread().getStackTrace();
if(stackTraceElements.length<3)
{
//当最后一个调用的方法不可用时,请执行某些操作
//也许你会想要归还一些东西
}
字符串callerMethod=stackTraceElements[2].getMethodName();
如果(调用方法等于(“m1”))
{
//某物
}否则
{
//别的
}
这个例子被简化了,因为它假设调用这个方法的方法是候选方法——它可以是调用堆栈下的某个方法


如上所述,不建议这样做。相反,应使用不同类型的比较器,并为排序方法提供一个相关的比较器,以便根据上下文进行不同类型的排序。

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


这仍然是一个难题。

您的问题中没有足够的信息,请提供“基于x上的某个时间和y上的某个时间”。请详细描述这一点。这方面的规则是什么?简短的回答是肯定的,但要正确回答,你是说有些实例比较x,有些比较y,有些比较两者?或者你的意思是,在某些条件下,所有实例要么比较x,y,要么两者都比较?@Bohemian-但我们的要求是比较这个类的两个对象,有时基于x,有时基于y:回答得好。我不知道如果m1调用m2会发生什么,反之亦然。@eis谢谢,我对这个答案很满意,我会在我们的项目中实现这个概念。谢谢lot@Johnson没问题。如果你觉得这个问题得到了回答,你应该将这个答案标记为已接受。
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
}