有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    在equals方法中,您将这个对象的atomLetter与它自身进行比较

    if (atomLetter == this.atomLetter){ 
    

    相反,您需要将obj参数强制转换为Element类,并将其atomLetterthis.atomLetter进行比较

    Element other = (Element) obj;
    return this.atomLettet == other.atomLettet;
    

    当然,在实际执行之前,您可能会想测试强制转换是否可行,如果对象属于不同的类,则表示它们不相等。还要测试null。对象的javadoc。Equals()解释了正确Equals方法的所有要求

  2. # 2 楼答案

    可以通过这种方式实现equals方法。然而,您还必须实现哈希代码以确保正确性

    为了平等

    @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);
     }
    

    对于hashcode,您可以通过多种方式实现它,但通常这是最快、最简单的方式

    @Override
    public int hashCode()
    {
      return Objects.hash(atomLetter, name);
    }
    
  3. # 3 楼答案

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

    比较内容,而不是参考资料

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

    始终通过调用^{}^{}来比较^{}内容

    为了实现^{,您可以测试引用是否相同,这是平等性测试的第一部分。但光靠这一点是不够的

    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

    在实现equals时始终实现hashCode

    正如在堆栈溢出(例如here)上多次讨论的那样,在编写^{}方法时,始终使用相同的逻辑编写^{}方法

    @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 + '\'' +
                    " }";
        }
    }