在 equals 方法中比较两个对象名称
Comparing two objects names in an equals method
我不太了解如何正确比较我正在测试的对象。我的问题是,由于代码的原因,测试本身总是正确的,但我想到的任何其他方式也不能正常工作。
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));
}
在您的 equals 方法中,您将此对象的 atomLetter
与其自身进行比较。
if (atomLetter == this.atomLetter){
相反,您需要将 obj
参数转换为 Element
class 并将其 atomLetter
与 this.atomLetter
进行比较
Element other = (Element) obj;
return this.atomLettet == other.atomLettet;
当然,您可能希望在实际执行之前测试转换是否可行,并说如果对象 class 不同则对象不相等。还要测试是否为空。 object.Equals() 的 javadoc 解释了所有正确的 equals 方法的要求。
关于 this.atomLetter
与自身的比较, 是正确的。 equals
.
还有一些其他问题
比较内容,而不是参考文献
您的代码 … == this.atomLetter
正在比较对象引用(指针),而不是那些 String
对象的文本 内容。换句话说,你问的是这两个变量是否都引用同一个对象,即同一个内存块。
总是比较String
content by calling String::equals
or String::equalsIgnoreCase
。
为了实现 equals
,您 可以 测试引用是否相同,作为相等性测试的快速第一部分。但仅此还不够。
if ( this == other ) return true;
测试空值
您应该测试 null
。如果其他对象引用为null,则没有对象,所以不能相等。
if ( other == null ) return false;
测试 class
您还可以确保两个对象的 class 匹配。
if ( other == null || getClass() != other.getClass() ) return false;
演员表
正如另一个答案提到的,您应该投射通过的 Object
,已经通过上面显示的 class-匹配测试。
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
正如在 Stack Overflow 上多次讨论的那样,例如 here, when writing an equals
method, always write a hashCode
使用相同逻辑的方法。
@Override
public int hashCode ( )
{
return Objects.hash( getAtomLetter() );
}
示例class
所以我们最终得到 Element
class 看起来像这样。
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 + '\'' +
" }";
}
}
您可以通过这种方式实现 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);
}
我不太了解如何正确比较我正在测试的对象。我的问题是,由于代码的原因,测试本身总是正确的,但我想到的任何其他方式也不能正常工作。
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));
}
在您的 equals 方法中,您将此对象的 atomLetter
与其自身进行比较。
if (atomLetter == this.atomLetter){
相反,您需要将 obj
参数转换为 Element
class 并将其 atomLetter
与 this.atomLetter
Element other = (Element) obj;
return this.atomLettet == other.atomLettet;
当然,您可能希望在实际执行之前测试转换是否可行,并说如果对象 class 不同则对象不相等。还要测试是否为空。 object.Equals() 的 javadoc 解释了所有正确的 equals 方法的要求。
关于 this.atomLetter
与自身的比较,equals
.
比较内容,而不是参考文献
您的代码 … == this.atomLetter
正在比较对象引用(指针),而不是那些 String
对象的文本 内容。换句话说,你问的是这两个变量是否都引用同一个对象,即同一个内存块。
总是比较String
content by calling String::equals
or String::equalsIgnoreCase
。
为了实现 equals
,您 可以 测试引用是否相同,作为相等性测试的快速第一部分。但仅此还不够。
if ( this == other ) return true;
测试空值
您应该测试 null
。如果其他对象引用为null,则没有对象,所以不能相等。
if ( other == null ) return false;
测试 class
您还可以确保两个对象的 class 匹配。
if ( other == null || getClass() != other.getClass() ) return false;
演员表
正如另一个答案提到的,您应该投射通过的 Object
,已经通过上面显示的 class-匹配测试。
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
正如在 Stack Overflow 上多次讨论的那样,例如 here, when writing an equals
method, always write a hashCode
使用相同逻辑的方法。
@Override
public int hashCode ( )
{
return Objects.hash( getAtomLetter() );
}
示例class
所以我们最终得到 Element
class 看起来像这样。
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 + '\'' +
" }";
}
}
您可以通过这种方式实现 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);
}