在equals方法中比较两个对象名称

时间:2020-06-21 20:20:11

标签: java equals

我对如何正确比较正在测试的对象有些困惑。我的问题是,由于代码的原因,测试本身总是正确的,但是我想到的任何其他方式也都无法正常工作。

public class Element {

    private String atomLetter;
    private String name;

    public Element(String atomLetter, String name) {
        this.atomLetter = atomLetter.toUpperCase();
        this.name = name.toLowerCase();
    }

    public Element(String atomLetter) {
        this(atomLetter, "");
    }

    public String getAtomLetter() {
        return atomLetter;
    }

    public String getName() {
        return name;
    }

    // TODO: two elements are considered to be equal if they have the same atom letter.
    @Override
    public boolean equals(final Object obj) {



        if (atomLetter == this.atomLetter){

            return true;
        }

        return false;

    }

    @Override
    public String toString() {
        return "Element{" +
                "'" + atomLetter + "'" +
                ", name='" + name + '\'' +
                '}';
    }
}

在这种情况下,结果完全一样,但是问题是equals方法。

@Test
public void testSimpleMolecules() {
    // simple carbon
    Molecule m1 = new Molecule("");
    assertTrue(m1.isEmpty());
    assertEquals(0, m1.size());
    m1.add(new Element("C"));
    assertFalse(m1.isEmpty());
    assertEquals(1, m1.size());
    assertEquals(new Element("C"), m1.get(0));
    // simple hydrogen
    Molecule m2 = new Molecule("");
    m2.add(new Element("H"));
    assertFalse(m2.isEmpty());
    assertEquals(1, m2.size());
    assertEquals(new Element("H"), m2.get(0));
    // simple nitrogen
    Molecule m3 = new Molecule("");
    m3.add(new Element("N"));
    assertFalse(m3.isEmpty());
    assertEquals(1, m3.size());
    assertEquals(new Element("N"), m3.get(0));
    // simple oxygen
    Molecule m4 = new Molecule("");
    m4.add(new Element("O"));
    assertFalse(m4.isEmpty());
    assertEquals(1, m4.size());
    assertEquals(new Element("O"), m4.get(0));
}

3 个答案:

答案 0 :(得分:3)

在equals方法中,您正在将该对象的atomLetter与自身进行比较。

if (atomLetter == this.atomLetter){ 

相反,您需要将obj参数转换为Element类,并将其atomLetterthis.atomLetter

进行比较。
Element other = (Element) obj;
return this.atomLettet == other.atomLettet;

当然,您可能需要在实际进行转换之前测试其是否可以转换,并说如果对象属于不同的类,则它们是不相等的。同时测试是否为空。 object.Equals()的Javadoc解释了所有对适当equals方法的要求。

答案 1 :(得分:2)

关于您将this.atomLetter与自身进行比较,Answer by DarkSigma是正确的。 equals还有其他一些问题。

比较内容,而不是引用

您的代码… == this.atomLetter正在比较对象引用(指针),而不是那些String对象的文本 content 。换句话说,您要问两个变量是否都指向同一个对象,即相同的内存块。

始终通过调用StringString::equals比较String::equalsIgnoreCase的内容。

要实现equals,您可以 测试引用是否相同,这是等同测试的快速第一部分。但这还不够。

if ( this == other ) return true;

测试是否为空

您应该测试null。如果另一个对象引用为null,则没有对象,因此不会存在相等性。

 if ( other == null ) return false;

测试课程

您还可以确保两个对象的类匹配。

 if ( other == null || getClass() != other.getClass() ) return false;

发布

正如提到的其他答案一样,您应该在通过以上所示的类匹配测试之后,对通过的Object进行转换。

Element element = ( Element ) other;

检查内容是否匹配

作为最后一个测试,请检查匹配的内容。

在这种情况下,我怀疑您要做关心大小写匹配。所以我们称String::equals而不是String::equalsIgnoreCase

return getAtomLetter().equals( element.getAtomLetter() );

示例equals方法

让我们将所有内容整合到一个equals实现中。

@Override
public boolean equals ( Object other )
{
    if ( this == other ) return true;
    if ( other == null || getClass() != other.getClass() ) return false;
    Element element = ( Element ) other;
    return getAtomLetter().equals( element.getAtomLetter() );
}

提示:您的IDE将为您生成此代码。无需自己写。例如,在IntelliJ中,选择:Code> Generate> equals() and hashCode

实施hashCode时始终实施equals

正如在堆栈溢出问题上多次讨论的,例如here,在编写equals方法时,请始终使用相同的逻辑来编写hashCode方法。

@Override
public int hashCode ( )
{
    return Objects.hash( getAtomLetter() );
}

示例类

所以我们最终得到了一个Element类,看起来像这样。

package work.basil.example;

import java.util.Objects;

public class Element
{
    // Member fields
    private String atomLetter, name;

    // Constructor
    public Element ( String atomLetter , String name )
    {
        this.atomLetter = Objects.requireNonNull( atomLetter ).toUpperCase();
        if ( this.atomLetter.isBlank() ) { throw new IllegalArgumentException();}
        this.name = Objects.requireNonNull( name ).toLowerCase();
    }

    // Getters (read-only).
    public String getAtomLetter ( ) {return atomLetter;}

    public String getName ( ) {return name;}

    // `Object` overrides

    @Override
    public boolean equals ( Object other )
    {
        if ( this == other ) return true;
        if ( other == null || getClass() != other.getClass() ) return false;
        Element element = ( Element ) other;
        return getAtomLetter().equals( element.getAtomLetter() );
    }

    @Override
    public int hashCode ( )
    {
        return Objects.hash( getAtomLetter() );
    }

    @Override
    public String toString ( )
    {
        return "Element{ " +
                "atomLetter='" + atomLetter + '\'' +
                " | name='" + name + '\'' +
                " }";
    }
}

答案 2 :(得分:0)

您可以通过这种方式实现equals方法。但是,还必须实现hashCode以确保正确性。

等于

@Override
public boolean equals(Object obj)
{
   // check the instance of obj
   if (!(obj instanceof Element)) return false;
   
   // check if obj is itself
   if (obj == this) return true;
   
   // cast obj as Element
   Element e = (Element) obj;
   
   // compare fields
   return this.atomLetter.equals(e.atomLetter) &&
   this.name.equals(e.name);
 }

对于哈希码,您可以通过多种方法来实现,但是通常这是最快,最简单的方法。

@Override
public int hashCode()
{
  return Objects.hash(atomLetter, name);
}