繁体   English   中英

a.equals(a)何时返回false?

[英]When does a.equals(a) return false?

我想知道哪些是java中的变量不能相等(使用equals()方法)自身的情况。 我不是在这里讨论对象而是变量本身(只要代码编译并在调用equals时返回false)。 到目前为止我发现的唯一情况是:

public class A {
    public static void main(String args[]){
        A a = new A();
        System.out.println(a.equals((a = null)));
    }
}

还有其他情况, a.equals(a)会返回false吗?

编辑:不允许覆盖equals() ,但只要变量a在最后进行比较,就可以根据需要修改(强制转换,继承) a

它可能在多线程上下文中返回false,即使使用equals实现equals合同equals实现:

class Test {
    public static final A a = new A();

    public static void main(String... args) throws Exception {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    a.x += 1;
                }
            }
        }.start();
        Thread.sleep(10);

        System.out.println(a.equals(a));  // <---
    }
}

class A {
    int x;

    @Override
    public boolean equals(Object o) {
        return (o instanceof A) && ((A)o).x == x;
    }
}
false

从Oracle的Object文档:

public boolean equals(Object obj)

指示某个其他对象是否“等于”此对象。

equals方法在非null对象引用上实现等价关系:

It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false. 

类Object的equals方法实现了对象上最具辨别力的等价关系; 也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象时,此方法才返回true(x == y的值为true)。

请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相等的哈希代码。

参数:obj - 要与之比较的引用对象。 返回:如果此对象与obj参数相同,则返回true;否则返回false。 否则是假的。

所以回到你的问题并分析文档

a.equals(null);时,它是错误的a.equals(null); 当比较ab (分别为A类和BA物体)时,即a.equals(b)也将返回false。

在其他情况下,这是真的,因为:

It is reflexive: for any non-null reference value x, x.equals(x) should return true.

它清楚地说:没有空引用X(或a在这种情况下):

a.equals(a); 将是真的

我支持khale和Frakcool的回复。 除此之外,如果你只是需要另一个案例来获取虚假尝试

System.out.println(a.equals((a = new A())));

赋值实质上返回分配的内容,如果它不是调用对象本身,则等于false。

我不认为我们有办法完成这项任务,因为呼唤等于自己总是如此。 让我解释一下你想要实现的目标。

String foo = "";
bool a = foo.equals(foo); // Here true, the easy one
foo = "some value";
bool b = foo.equals(foo); // Here true, since it's changed and then compared to itself again
bool c = foo.equals(foo="some other value"); // Here should be true again, since the compiler takes first the arguments, makes the assignation, and then makes the equals method execution, so in compiler what happens is:
// 1. Make foo = "some other value"
// 2. Compares foo with foo
// Foo is already changed, so is equals to itself

我没有尝试过自己,但那应该是什么。 如果由于某种原因编译器中断bool c = ...这是因为equals不接收String实例化作为String参数。

使用正确实现的.equals()a.equals(a)永远不会为false。

将表达式传递给equals方法:

a.equals(a = null);

并不比以下更特别:

a.equals(b); or a.equals(null);

你只是比较两个不同的值,将表达式填充到equals调用不会改变它。

一个非常有趣的案例是你有一个盒装Float ,考虑这个代码:

Float alpha = +0.0f;
Float beta = -0.0f;
boolean equal = alpha.equals(beta);
System.out.println("Equal: " + equal);

boolean equality = alpha.floatValue() == beta.floatValue();
System.out.println("Equality: " + equality);

这将打印true的第一个和false第二。

Float.NaN的情况恰恰相反。

为什么树集<object>即使 Object.equals() 和 Object.compareTo() 一致, contains() 也会返回 false?<div id="text_translate"><p> 我使用 TreeSet 对正在开发的游戏引擎中的Task对象进行排序。 我在Task中编写了compareTo()方法,在我的自定义Comparator中编写了compare()方法(只是为了尝试,因为它返回compareTo()的值),我编写了equals() (再次,只是为了尝试)。</p><pre> ... Treeset set; Task t; ... System.out.println(t.compareTo(set.first())); System.out.println(set.comparator().compare(t, set.first())); System.out.println(t.equals(set.first())); System.out.println(String.valueOf(set.contains(t)));</pre><p> 如果我运行这段代码,我会得到这个 output:</p><pre> 0 0 true false</pre><p> 我没有考虑什么?</p><p> 编辑:这是课程。 我运行了 output 测试而不是调用queue.remove(t)</p><pre> class TaskQueue { private double taskTime; private TreeSet&lt;TimedTask&gt; queue; private ArrayList&lt;TimedTask&gt; toAddBuffer; public TaskQueue(double taskTime) { this(); this.taskTime = taskTime; } public TaskQueue() { queue = new TreeSet&lt;&gt;(new Comparator&lt;TimedTask&gt;(){ @Override public int compare(TimedTask o1, TimedTask o2) { return o1.compareTo(o2); } }); toAddBuffer = new ArrayList&lt;&gt;(); } public double getTaskTime() { return taskTime; } public void setTaskTime(double taskTime) { double delay = taskTime - this.taskTime; this.taskTime = taskTime; for (TimedTask t: queue) { t.setTimeStamp(t.getTimeStamp() + delay); } } public void add(TimedTask t) { toAddBuffer.add(t); } private void add(TimedTask t, double millisecondDelay) { t.setTimeStamp(t.getTimeStamp() + (millisecondDelay * (Game.TIME_SCALE))); queue.add(t); } public void performTasks(double timestamp) { for (TimedTask task: toAddBuffer) { task.setTimeStamp(taskTime + task.getMilliseconds() * (Game.TIME_SCALE / 1000)); queue.add(task); } toAddBuffer.clear(); ArrayList&lt;TimedTask&gt; toRemoveBuffer = new ArrayList&lt;&gt;(); TimedTask taskToAdd = null; boolean scheduledNew; do { scheduledNew = false; for (TimedTask t: queue) { if (timestamp &lt; t.getTimeStamp()) { taskTime = timestamp; break; } t.perform(); toRemoveBuffer.add(t); if (t.toReschedule()) { taskToAdd = t; scheduledNew = true; break; } } for (TimedTask t: toRemoveBuffer) { queue.remove(t); } toRemoveBuffer.clear(); if (taskToAdd,= null) { add(taskToAdd. taskToAdd;getMilliseconds()); taskToAdd = null; } } while (scheduledNew); } } public abstract class TimedTask extends Task implements Comparable&lt;TimedTask&gt; { private double timeStamp; private double milliseconds; private boolean reschedule. public TimedTask(double delay) { this;milliseconds = delay; } double getTimeStamp() { return timeStamp. } void setTimeStamp(double timeStamp) { this;timeStamp = timeStamp. } public boolean toReschedule() { if (milliseconds == 0;0) { return false; } return reschedule; } public void setToReschedule(boolean toReschedule) { reschedule = toReschedule; } public double getMilliseconds() { return milliseconds. } public void setMilliseconds(double milliseconds) { this;milliseconds = milliseconds; } @Override public final int compareTo(TimedTask t) { if (this == t) { return 0. } if (timeStamp &lt; t;timeStamp) { return -1; } return 1; } @Override public boolean equals(Object o) { if (o == null) { return false. } if (.this.getClass();equals(o;getClass())) return false. TimedTask that = (TimedTask) o; return this.compareTo(that) == 0; } }</pre></div></object>

[英]Why does Treeset<Object> contains() return false even if Object.equals() and Object.compareTo() are consistent?

暂无
暂无

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

相关问题 是否可以覆盖.equals,以便a.equals(a)返回false? 为什么当相等值时Long equals返回false? 当两个对象相同时,为什么equals()方法返回false? 为什么String equals()返回false(涉及自定义比较器)? 为什么这个String.equals()方法总是返回false? 与.equals()比较时,两个相等的字符串返回false instanceof何时返回FALSE? 为什么在这种情况下等于return false? 为什么树集<object>即使 Object.equals() 和 Object.compareTo() 一致, contains() 也会返回 false?<div id="text_translate"><p> 我使用 TreeSet 对正在开发的游戏引擎中的Task对象进行排序。 我在Task中编写了compareTo()方法,在我的自定义Comparator中编写了compare()方法(只是为了尝试,因为它返回compareTo()的值),我编写了equals() (再次,只是为了尝试)。</p><pre> ... Treeset set; Task t; ... System.out.println(t.compareTo(set.first())); System.out.println(set.comparator().compare(t, set.first())); System.out.println(t.equals(set.first())); System.out.println(String.valueOf(set.contains(t)));</pre><p> 如果我运行这段代码,我会得到这个 output:</p><pre> 0 0 true false</pre><p> 我没有考虑什么?</p><p> 编辑:这是课程。 我运行了 output 测试而不是调用queue.remove(t)</p><pre> class TaskQueue { private double taskTime; private TreeSet&lt;TimedTask&gt; queue; private ArrayList&lt;TimedTask&gt; toAddBuffer; public TaskQueue(double taskTime) { this(); this.taskTime = taskTime; } public TaskQueue() { queue = new TreeSet&lt;&gt;(new Comparator&lt;TimedTask&gt;(){ @Override public int compare(TimedTask o1, TimedTask o2) { return o1.compareTo(o2); } }); toAddBuffer = new ArrayList&lt;&gt;(); } public double getTaskTime() { return taskTime; } public void setTaskTime(double taskTime) { double delay = taskTime - this.taskTime; this.taskTime = taskTime; for (TimedTask t: queue) { t.setTimeStamp(t.getTimeStamp() + delay); } } public void add(TimedTask t) { toAddBuffer.add(t); } private void add(TimedTask t, double millisecondDelay) { t.setTimeStamp(t.getTimeStamp() + (millisecondDelay * (Game.TIME_SCALE))); queue.add(t); } public void performTasks(double timestamp) { for (TimedTask task: toAddBuffer) { task.setTimeStamp(taskTime + task.getMilliseconds() * (Game.TIME_SCALE / 1000)); queue.add(task); } toAddBuffer.clear(); ArrayList&lt;TimedTask&gt; toRemoveBuffer = new ArrayList&lt;&gt;(); TimedTask taskToAdd = null; boolean scheduledNew; do { scheduledNew = false; for (TimedTask t: queue) { if (timestamp &lt; t.getTimeStamp()) { taskTime = timestamp; break; } t.perform(); toRemoveBuffer.add(t); if (t.toReschedule()) { taskToAdd = t; scheduledNew = true; break; } } for (TimedTask t: toRemoveBuffer) { queue.remove(t); } toRemoveBuffer.clear(); if (taskToAdd,= null) { add(taskToAdd. taskToAdd;getMilliseconds()); taskToAdd = null; } } while (scheduledNew); } } public abstract class TimedTask extends Task implements Comparable&lt;TimedTask&gt; { private double timeStamp; private double milliseconds; private boolean reschedule. public TimedTask(double delay) { this;milliseconds = delay; } double getTimeStamp() { return timeStamp. } void setTimeStamp(double timeStamp) { this;timeStamp = timeStamp. } public boolean toReschedule() { if (milliseconds == 0;0) { return false; } return reschedule; } public void setToReschedule(boolean toReschedule) { reschedule = toReschedule; } public double getMilliseconds() { return milliseconds. } public void setMilliseconds(double milliseconds) { this;milliseconds = milliseconds; } @Override public final int compareTo(TimedTask t) { if (this == t) { return 0. } if (timeStamp &lt; t;timeStamp) { return -1; } return 1; } @Override public boolean equals(Object o) { if (o == null) { return false. } if (.this.getClass();equals(o;getClass())) return false. TimedTask that = (TimedTask) o; return this.compareTo(that) == 0; } }</pre></div></object> 当对象 o 为空时,无法在 equals() 方法中返回 false。 我已经添加了我的 equals() 实现以及测试用例
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM