Object的方法equals,hashCode,toString,clone。另外Comparable接口的方法

1、equals 方法和hashCode 方法实现示例:

public class EqualHashCodeTest {
	private boolean b;
	private int i;
	private float f;
	private double d;
	private String s;
	
	public EqualHashCodeTest() {
		super();
	}

	public EqualHashCodeTest(boolean b, int i, float f, double d, String s) {
		super();
		this.b = b;
		this.i = i;
		this.f = f;
		this.d = d;
		this.s = s;
	}

	//get/set方法

	@Override
	public boolean equals(Object object) {
		if(object==null || getClass()!=object.getClass()){
			return false;
		}
		
		EqualHashCodeTest hct = (EqualHashCodeTest) object;
		return 	b==hct.isB() &&
				i==hct.getI() &&
				0==Float.compare(f, hct.getF()) &&
				0==Double.compare(d, hct.getD()) && 
				s==null ? false : s.equals(hct.getS());
				//虽然 null == null,但是这没有意义!所以这里返回false
	}

	@Override
	public int hashCode() {
		int result = 17;
		
		result = 37*result + Boolean.valueOf(b).hashCode();
		result = 37*result + Integer.valueOf(i).hashCode();
		result = 37*result + Float.valueOf(f).hashCode();
		result = 37*result + Double.valueOf(d).hashCode();
		result = 37*result + (s==null ? 0 : s.hashCode());
		
		return result;
	}

}

继承时,equals 方法和hashCode 方法实现示例

class ExtendEqualHashCode extends EqualHashCodeTest{
	private String extendName;

	public String getExtendName() {
		return extendName;
	}

	public void setExtendName(String extendName) {
		this.extendName = extendName;
	}

	public ExtendEqualHashCode() {
		super();
		this.extendName = "DEFAULT";
	}

	public ExtendEqualHashCode(boolean b, int i, float f, double d, String s, String name) {
		super(b, i, f, d, s);
		this.extendName = name;
	}
	
	/**
	 * 父类的equals 方法会检查
	 * 1、object 是否为null
	 * 2、比较的两对象是否为同一 Class 对象
	 */
	@Override
	public boolean equals(Object object) {
		return super.equals(object) &&
			   extendName == null ? false : ((ExtendEqualHashCode)object).getExtendName().equals(extendName);
	}

	@Override
	public int hashCode() {
		int result = super.hashCode();
		result = 37*result + (extendName==null?0:extendName.hashCode());
		return result;
	}
	
}

2、toString 方法现实示例

规则:

a、对象用大括号包围 {....}

b、对象内的属性用中括号包围 [.....] ,各个属性之间用逗号分隔(,)

c、属性的表示格式为:$name=GongQiang

class PeopleForTest{
	private String name;
	private String sex;
	private int age;
	
	
	public PeopleForTest() {
		super();
	}
	
	public PeopleForTest(String name, String sex, int age) {
		super();
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	//get/set 方法

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((sex == null) ? 0 : sex.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if( obj == null || getClass() != obj.getClass() ){
			return false;
		}
		
		PeopleForTest people = (PeopleForTest)obj;
		
		return 	(age == people.age) &&
				stringEquals(name, people.name) && 
				stringEquals(sex, people.sex);
	}
	
	private boolean stringEquals( String s1, String s2 ){
		return s1 == null ? false : s1.equals(s2);
	}

	@Override
	public String toString() {
		String nameString = "[$name=" + name + "]";
		String sexString  = "[$sex=" + sex + "]";
		String ageString  = "[$age=" + age + "]";
		return "{" + nameString +","+ sexString + "," + ageString +"}";
	}
}

如下对象,如下toString 方法显示

PeopleForTest p = new PeopleForTest( "GongQiang", "man", 24);
System.out.println( p );
//output	
{[$name=GongQiang],[$sex=man],[$age=24]}

 

对集合的信息打印帮助类:

public class CollectionPrintHelper {
	
	//Used for print array
	public static <T> void printArrays( T[] array ){
		if( array == null ){
			System.out.println( "Array is null!" );
			return;
		}
		
		int index = 0;
		for( T e : array ){
			System.out.println( "[" + (index++) +"]:" + e );
		}
	}
	
	//Used for print Collection
	public static <E> void printCollection( Collection<E> c){
		if( c== null){
			System.out.println( "Collection is null!" );
			return;
		}
		
		int index = 0;
		for( E e : c){
			System.out.println( "[" + (index++) +"]:" + e );
		}
	}
	
	//Used for print Map
	public static <K, V> void printMap( Map<K, V> map ){
		if( map == null ){
			System.out.println("Map is null!");
			return;
		}
		
		int index = 0;
		for( Entry<K, V> entry : map.entrySet() ){
			String key 		= entry.getKey().toString();
			String value 	= entry.getValue().toString();
			
			System.out.print( "[" + (index++)+ "]:");
			System.out.println(key + "=" + value);
		}
	}
}

3、clone 方法实现示例(实现 Cloneable 接口)

限制:对象的field 也为对象,则该field 不能声明为 final !

原因:final 域,有两种方式来初始化,1、直接赋值;2、构造时赋值

当深度克隆时,会有如下语句:

m.hireDay = (Date) hireDay.clone();
如果hireDay 声明为final ,则语法错误!
class Member implements Serializable ,Cloneable ,Comparable<Member>{
	
	private static final long serialVersionUID = 259178685941754554L;
	
        //other fields get/set method
	//public void setSalary(double salary) {
		//this.salary = salary;
	//}

	private String name;
	private final double salary;
	private Date hireDay;
	private String department;
	
	@Override
	public Member clone() throws CloneNotSupportedException {
		Member m = (Member) super.clone();
		m.hireDay = (Date) hireDay.clone();
		return m;
	}

	@Override
	public boolean equals(Object o) {
		if( o==null || getClass()!=o.getClass()){
			return false;
		}
		return fieldEquals(o);
	}

	private boolean fieldEquals(Object o){
		Member m = (Member)o;
		return name==null ? false : name.equals(m.getName()) &&
			   0==Double.compare(salary, m.getSalary())  &&
			   hireDay==null ? false : hireDay.getTime() == m.getHireDay().getTime() &&
			   department==null ? false : department.equals(m.getDepartment());
	}

	
        //salary is fianl, must give it value when construct!
	//public Member() {

	//}
	
	public Member(String name ,double salary ,int year ,int month ,int day){
		this.name = name;
		this.salary = salary;
		GregorianCalendar calendar = new GregorianCalendar(year ,month-1 ,day);
		hireDay = calendar.getTime();
	}
	
	public Member(String name,double salary, int year ,int month ,int day ,String depart){
		this.name = name;
		this.salary = salary;
		GregorianCalendar calendar = new GregorianCalendar(year ,month-1 ,day);
		hireDay = calendar.getTime();
		department = depart;
	}
	
	public String toString(){
		return 	"{" + "[$name="+name+ "]" +
				",[$salary=" + salary + "]" +
				",[$hireDay=" + hireDay+"]" + 
				",[$department="+ department + "]" +
				"}";
	}

	@Override
	public int compareTo(Member member) {
		if (getClass() != member.getClass()) throw new ClassCastException();
		if(salary < member.salary)return -1;
		if(salary > member.salary)return 1;
		return 0;
	}
}

要正确实现某个类的 clone 方法

1、父类的 clone 方法必须都正确实现

2、类的对象域还不能声明为 final

可见 clone 方法的限制还是蛮多的,可以自定义copy 的方法:copy constructor 或 copy factory

	//copy constructor
	public Member( Member member ){
		this.name = member.getName();
		this.salary = member.getSalary();
		this.hireDay = new Date( member.getHireDay().getTime() );
		this.department = member.getDepartment();
	}
	//copy factory
	public static Member copy( Member member ){
		
		return new Member( member );
	}

4、Comparable 的 compareTo 方法

注意:子类继承父类的 compareTo 方法时,要保存比较的对称性!

因而加了一个判断,是否为同一 Class !

class ExtendMember extends Member{
	
	private static final long serialVersionUID = -2054912134719304214L;
	private Member secretary;
	private double donus;

	//get/set methods
	
	@Override
	public int compareTo(Member member) {
		if (getClass() != member.getClass()) throw new ClassCastException();
		ExtendMember em = (ExtendMember) member;
		if(donus < em.donus)return -1;
		if(donus > em.donus)return 1;
		return 0;
	}
	@Override
	public ExtendMember clone() throws CloneNotSupportedException {
		ExtendMember em = (ExtendMember) super.clone();
		em.setSecretary((Member)this.getSecretary().clone());
		
		return em;
	}

	@Override
	public boolean equals(Object o) {
		if(!super.equals(o))return false;
		
		ExtendMember em = (ExtendMember) o;
		return secretary.equals(em.secretary);
	}
	
	public ExtendMember(String name ,double salary ,int year ,int month ,int day ,String department){
		super(name ,salary ,year ,month ,day ,department);
		secretary = null;
	}
	
	//保持打印信息格式
	public String toString(){
		return removeLastString(super.toString()) + ",[secretary=" + secretary +"]}";
	}
	protected String removeLastString( String str ){
		if( str == null ){
			return null;
		}
		return str.substring(0, str.length()-1);
	}
}
compareTo 方法与 equals 方法一致,即:(x.compareTo(y)==0) == (x.equals(y)),强烈推荐!
compareTo 方法与 equals 方法不一致,即:(x.compareTo(y)==0) != (x.equals(y))

示例如下:

public class ComparableVSEqeal {
	public static void main(String[] args) {
		BigDecimal bd1 = new BigDecimal("1.0");
		BigDecimal bd2 = new BigDecimal("1.00");
		
		System.out.println("bd1 equals bd2: " + bd1.equals(bd2));
		Set<BigDecimal> set = new HashSet<BigDecimal>();
		set.add(bd1);
		set.add(bd2);
		CollectionPrintHelper.printCollection(set);
		
		System.out.println("-------------------");
		
		System.out.println("bd1 compareTo bd2: " + bd1.compareTo(bd2));
		set = new TreeSet<BigDecimal>(set);
		CollectionPrintHelper.printCollection(set);
	}
}
输出结果:

bd1 equals bd2: false
[0]:1.0
[1]:1.00
-------------------
bd1 compareTo bd2: 0
[0]:1.0


排序时有多个项:

public int compareTo(PhoneNumber pn) {
	// Compare area codes
	if (areaCode < pn.areaCode)return -1;
	if (areaCode > pn.areaCode)return  1;
	
	// Area codes are equal, compare prefixes
	if (prefix < pn.prefix)return -1;
	if (prefix > pn.prefix)return  1;
	
	// Area codes and prefixes are equal, compare line numbers
	if (lineNumber < pn.lineNumber)return -1;
	if (lineNumber > pn.lineNumber)return  1;
	
	return 0; // All fields are equal
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值