`
zhuyuyuseu
  • 浏览: 9143 次
  • 性别: Icon_minigender_1
  • 来自: 南通
社区版块
存档分类
最新评论

遵守equals和hashCode方法的通用约定 (1)

    博客分类:
  • Java
阅读更多
  覆盖equals方法和hashCode方法看似简单,但其实不然,如果没有按照jdk的通用规范去覆盖,那么基于这些约定的类将可能无法正常工作,例如基于散列的集合类HashMap和HashSet.
  对于值类,我们通常需要覆盖Object.equals方法,因为我们希望通过equals方法知道它们在逻辑上是否相等.相应的这个类的实例可以被用作map的key,或者set的元素的时候才会表现出预期的行为. 对于"值类",枚举是个例外,因为枚举的每个值都是个单例.
  在覆盖equals时,必须遵守JavaSE Object的规范:自反性(reflective), 对称性 (symmetric),传递性(transitive),一致性(consistent),对于任何非null的引用x, x.equals(null)返回false. 对于每个覆盖类equals的类,都应该有相应的单元测试去检查是否有没有违反上述约定。下面是个简单的例子:

public class PhoneNumber {

	private int countryCode;
	private String nationalNumber;
	
	public PhoneNumber(){
		super();
	}
	
	public PhoneNumber(int countryCode, String nationalNumber) {
		super();
		this.countryCode = countryCode;
		this.nationalNumber = nationalNumber;
	}
	/**
	 * @return the countryCode
	 */
	public int getCountryCode() {
		return countryCode;
	}
	/**
	 * @param countryCode the countryCode to set
	 */
	public void setCountryCode(int countryCode) {
		this.countryCode = countryCode;
	}
	
	/**
	 * @return the nationalNumber
	 */
	public String getNationalNumber() {
		return nationalNumber;
	}
	/**
	 * @param nationalNumber the nationalNumber to set
	 */
	public void setNationalNumber(String nationalNumber) {
		this.nationalNumber = nationalNumber;
	}
	@Override
	public boolean equals(Object o){
		if(this == o){
			return true;
		}
		if(!(o instanceof PhoneNumber)){
			return false;
		}
		PhoneNumber pn = (PhoneNumber) o;
		return this.countryCode == pn.getCountryCode()
				&& ( this.nationalNumber == null ?  pn.nationalNumber == null : this.nationalNumber.equals(pn.nationalNumber));
	}	
}

import static org.junit.Assert.*;

import org.junit.Test;

public class PhoneNumberTest {

	@Test
	public void testEqualsReflexive(){
		PhoneNumber pn1 = new PhoneNumber(86, "12345");
		assertTrue(pn1.equals(pn1));
		PhoneNumber pn2 = new PhoneNumber();
		assertTrue(pn2.equals(pn2));
	}
	
	@Test
	public void testEqualsSymmetric(){
		PhoneNumber pn1 = new PhoneNumber(86, "12345");
		PhoneNumber pn2 = new PhoneNumber(86, "12345");
		assertEquals(pn1.equals(pn2), pn2.equals(pn1));
	}
	
	
	@Test
	public void testEqualsTransitive(){
		PhoneNumber pn1 = new PhoneNumber(86, "12345");
		PhoneNumber pn2 = new PhoneNumber(86, "12345");
		PhoneNumber pn3 = new PhoneNumber(86, new String("12345"));
		assertTrue(pn1.equals(pn2));
		assertTrue(pn2.equals(pn3));
		assertTrue(pn1.equals(pn3));
	}
	
	@Test
	public void testEqualsConsistent(){
		PhoneNumber pn1 = new PhoneNumber(86, "12345");
		PhoneNumber pn2 = new PhoneNumber(86, "12345");
		for(int i=0; i<10 ; i++){
			assertTrue(pn1.equals(pn2));
		}
	}
	
	@Test
	public void testEqualsWithNull(){
		PhoneNumber pn1 = new PhoneNumber(86, "12345");
		assertFalse(pn1.equals(null));
	}
	
}


当然还有一些实现高质量equals方法的诀窍:
   1. 使用==操作符检查"参数是否为正确的引用"
   2. 使用instanceof检查类型
   3. 把参数转化为正确的类型
   4. 选择逻辑比较的关键域,注意比较的顺序,primitive的比较可以放在前面,或者最有可能不一致性的域
   5. 如果有double,float类型,用Double.compare,Float.compare比较
   6. 覆盖equals重要覆盖hashCode
分享到:
评论
2 楼 Vicky.Hu 2014-02-25  
我来抢个2楼,
1 楼 wengeldouble 2014-02-25  
哈哈 第一个访客   这样子的授课模板 灰常灰常好

相关推荐

    Java容器集合(equals 和 hashCode+基础数据结构+ArrayList+Vector和LinkedList)

    重写equals方法需要遵守通用约定,hashCode方法的实现需要保证equals相同的两个对象的hashCode结果一致。ArrayList、Vector和LinkedList是Java中三种常见的容器集合,每种集合都有其特点和应用场景。

    学习Object类——为什么要重写equeals和hashcode方法

    此外,Object 类的设计是为了扩展,它提供了一些非 final 方法,如 equals、hashCode、toString、clone 和 finalize,这些方法都有通用的约定,需要在子类中被覆盖(override)。如果不遵守这些约定,依赖这些约定的...

    详解hashCode()和equals()的本质区别和联系

    在重写 equals() 方法时,需要遵守通用约定,包括: 1. 自反性:对于任意的引用值 x,x.equals(x) 一定为 true。 2. 对称性:对于任意的引用值 x 和 y,当 x.equals(y) 返回 true 时,y.equals(x) 也一定返回 true...

    java中equals和==的区别.pdf

    在Java编程语言中,`equals()`方法和`==`运算符是两个经常用来比较对象的...同时,为了确保其他自定义类的`equals()`方法正确实现,应遵循通用约定,即同时重写`equals()`和`hashCode()`方法,以保持一致性和正确性。

    Java中Equals使用方法汇总

    在Java编程中,`equals`方法是用于比较两个对象是否相等的重要方法。...遵循通用约定和同时更新`hashCode`方法能确保一致性和正确性。通过理解和实践这些原则,开发者可以创建出更可靠、更具可维护性的Java应用程序。

    高效Java 第三部分,经典的国外教材

    遵循 `equals()` 方法的通用约定可以帮助开发人员编写出更加健壮和易于维护的代码。此外,理解何时以及如何重写 `equals()` 方法对于创建高质量的Java应用程序至关重要。通过遵循上述指导原则,可以确保在实际应用中...

    Java核心技术(1).pdf

    - **项03:覆盖equals时请遵守通用约定**:正确的equals方法实现对于确保对象一致性至关重要。 #### 代码设计原则 - **项04:始终覆盖hashCode**:当重写了equals方法时,必须同时重写hashCode方法以保持一致性。 ...

    JPL_Coding_Standard_Java

    10. **R10:同时定义equals()和hashCode()方法** - 如果重写了`equals()`方法,则也应该重写`hashCode()`方法。 - 这样可以确保当两个对象相等时,它们具有相同的哈希码。 11. **R11:添加新字段时重新定义equals...

    core java达内培训资料

    根据给定的文件信息,以下是对“core java...Object是所有Java类的根类,提供了如toString()、equals()、hashCode()等基础方法,用于支持对象的基本操作。理解并适当重写这些方法对于编写高质量的Java代码至关重要。

    JAVA代码编写方法

    2. **基本方法实现**:为通用目的创建的类,应包含`equals()`、`hashCode()`、`toString()`、`clone()`(实现`Cloneable`)和`Serializable`接口,以提供标准的行为。 3. **测试代码**:每个类都应该有一个`main()`...

    面向对象OO程序设计概念PPT课件.PPTx

    **Java中的Object类**:在Java中,所有类都直接或间接地继承自Object类,它提供了所有Java对象通用的行为,如toString()、equals()和hashCode()等方法。通过继承,我们可以为特定类添加额外的功能,同时保持与Java...

    阿里巴巴JAVA开发规范doc版

    集合处理部分提供了处理集合时的建议,如避免null元素、正确使用equals()和hashCode()等。并发处理部分讲述了多线程编程中的最佳实践,包括锁的使用、线程安全的变量等。控制语句的规约指导如何有效使用if、for、...

    写Java程序的三十个基本规则.doc

    2. **通用方法**:为类提供`equals()`、`hashCode()`、`toString()`、`clone()`(实现`Cloneable`)和`implement Serializable`,以支持比较、哈希计算、字符串表示和克隆功能。 3. **测试代码**:为每个类创建一个...

    Java编程规范

    变量和方法名使用小驼峰命名法,如`myVariableName`;常量全大写,单词间用下划线分隔,如`MY_CONSTANT`。 2. **注释**:良好的注释能够帮助他人理解代码。类注释通常描述类的功能和用途,方法注释解释方法的作用和...

    平台Java代码编程规范

    - 重写`equals()`和`hashCode()`方法时,确保满足对象相等性的约定。 - 尽可能使用接口而非具体类进行类型声明,提高代码的灵活性。 【开发EJB规则】 - 遵守Enterprise JavaBeans(EJB)的官方规范,如实体Bean、...

    JAVA代码编写的30条建议

    2. **基础方法**:为通用类提供`equals()`、`hashCode()`、`toString()`、`clone()`(实现`Cloneable`)和`Serializable`接口,以支持基本操作和序列化。 3. **测试代码**:为每个自定义类创建一个`main()`方法,...

    java 编程规则

    - 创建通用类时,应包含常用的方法:`equals()`、`hashCode()`、`toString()`、`clone()`(实现`Cloneable`)和`Serializable`接口。 3. **测试代码**: - 为每个类提供一个`main()`方法用于测试,方便检查和验证...

    java编程30条规则

    2. **常规类设计**:创建通用类时,包括`equals()`、`hashCode()`、`toString()`、`clone()`(实现`Cloneable`)和`Serializable`接口。这些方法提供了基本的对象操作和比较。 3. **测试代码**:每个类都应该有一个...

    JAVA三十个注意

    为了确保对象的正确比较和操作,应实现`equals()`, `hashCode()`, `toString()`等方法。如果类实现了`Cloneable`接口,还需提供`clone()`方法;若要序列化对象,则需实现`Serializable`接口。这些方法的正确实现对于...

Global site tag (gtag.js) - Google Analytics