两个对象的相等是否意味着什么?

时间:2016-06-17 17:51:09

标签: java

我们可以通过覆盖相应类中的equals / hashcode方法来比较两个对象,但是,这两个对象在我们的编写方法(equals / hashcode)的上下文中将是相同的!

即使我们发现这两个对象具有相同的所有属性值,这是否真的意味着什么呢?我的意思是,根据编译器/ JVM,这两个将是不同的对象,对吧?我想他们也会拥有两个不同的记忆位置,不是吗?

(我是Java的新手,所以如果我说了一些非常愚蠢的话,我会很感激,如果你能纠正我。或者如果你需要明确任何事情,请随意提问。但鉴于此事实上,我要求所有请不要让我完全改变我的问题或结构。提前致谢!)

2 个答案:

答案 0 :(得分:0)

在理论上是的,它并不重要,但是对于你编写的所有应用程序来说并不是这样吗?但每当我比较一个对象时,我知道它引用了相同的数据库记录,因为ID是相同的(和类型),它对我的​​代码很有价值。例如,您可以确保您的对象不在列表中,您可以在列表中有两个不同的实例,而您需要一个数据库对象的唯一表示列表,那么.equals函数将变得有用。

如果你需要知道它是否是完全相同的实例,你可能不应该覆盖.equals方法。像其他人说的那样重要的是两个包含相同文本值的字符串,例如:

function foo() {
    String bar = "I'm cool";
    String baz = "I'm cool";

    assertTrue(bar.equals(baz)); //true
    assertTrue(bar == baz); //false
}

示例可能有误,但这是不同之处。如果重写equals方法对JVM无关紧要,那么JVM就没有良心。

玩得开心!

答案 1 :(得分:0)

你的问题太多混乱,缺乏连贯性。你写道:

  

我们可以通过覆盖相应类

中的equals / hashcode方法来比较两个对象
不,你不是。在执行某些操作时比较两个对象,例如:

    String firstString = "asdf";
    int result = firstString.compareTo("asdff");

你"比较"当您在实现compareToComparable)的类的对象上调用firstString方法时,将另一个对象("asdff")作为方法的实际参数传递。这就是它,它只是一个名称问题(类型的名称 - 类 - 以及方法的名称)。

关于等式运算符(==)和equals方法之间的区别,同样,它只是定义的问题。规则在此处定义https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.21

  

即使我们发现这两个对象具有相同的所有属性值,这是否真的意味着什么呢?

有什么对象?这些物体是什么类型的?他们的属性是什么类型的?这一切都取决于它们的实施方式。这个问题非常暧昧,但无论如何我都会说答案是否定的。在Java程序(或任何其他语言)的上下文中,平等并不意味着超出语言规范和代码定义的任何内容。

  

我想他们也会拥有两个不同的记忆位置,不是吗?

示例(如果您不理解"断言"事情,请检查JUnit。它只是意味着"这必须是真/假"):

@Test
public void testCrazy()
{        
    Object firstObject = new Object();
    // now I have a reference on the stack (firstObject) that points to some memory 
    // location on the heap that holds some bytes representing an Object instance
    Object secondObject = new Object();
    // now I have another reference pointing to a DIFFERENT location on the 
    // heap
    boolean equalReferences = (firstObject == secondObject);
    // equalReferences is expected to be false
    assertFalse(equalReferences);

    // look, I make the first reference point to the locations held by the
    // second one (tha is what = does if applied to references)
    firstObject = secondObject;
    // now the 2 references are expected to pass the equality operator test
    assertTrue(firstObject == secondObject);

    // what if I override equals in a completely nonsense way?
    firstObject = new Object(){
        @Override
        public boolean equals(Object obj)
        {
            // no matter what, it always returns false.
            // does it make sense? Probably not in our common sense, but the
            // compiler won't complain
            return false;
        }
    };

    secondObject = firstObject;
    // now they do point to same same memory location, in fact
    assertTrue(secondObject == firstObject);

    // but if I call the overriden equals method:
    assertFalse(firstObject.equals(secondObject));

    // it is still failing even if I call equals on firstObject itself:
    assertFalse(firstObject.equals(firstObject));
}