黑马程序员_对象的比较

-------android培训java培训、期待与您交流! ----------

Equals方法:

Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中这个方法判断两个对象是否有相同的引用。如果两个对象有相同的引用,它们一定是想等的。

然而,对于多数类来说,这种判断并没有什么意义。例如,采用这种方式比较两个PrintStream对象是否相等就完全没有意义。然而,经常需要检测两个对象的

相等性,如果两个对象的状态想等,就认为这两个对象是想等的。

 

下面给出编写一个完美的equals方法的建议:

1)     显示参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量。

2)     检测this与otherObject是否引用同一个对象:

if(this== otherObject) return true;

这条语句只是一个优化。实际上,这是一种经常采用的形式。因为计算这个等式要比一个一个比较类中的域代价要小得多。

3)     检测otherObject是否为null,如果为null,返回false,这项检测是很有必要的。

if(otherObject== null) return false;

4)     比较this与otherObject是否属于同一个类。如果equals的语义在每个子类中有所改变,就使用getClass检测:

if(getClass()!= otherObject.getClass()) return false;

      如果所有的子类都拥有统一的语义,就使用instanceof检测:

if(!(otherObject instanceofClassName)) return false;

5)     将otherObject转换成为相应的类类型变量:

ClassName other = (ClassName)otherObject;

6)     现在开始对所有需要比较的域进行比较了。使用==比较基本类型域,使用equals比较对象域。如果所有的域都匹配,就返回true,否则返回false。

return field1 == other.filed1
	&& filed2.equals(other.field2)
	&& …

如果在子类中重新定义equals,就要在其中包含调用super.equals(other)。

PS:对于数组类型的域,可以使用静态的Arrays.equals方法检测相应的数组元素是否想等。

从Java SE 5.0开始,为了避免发生类型错误,可以使用@Override对覆盖超类的方法进行标记:

@Override public Boolean equals(Objectother)

如果出现了错误,并且正在定义一个新方法,编译器就会给出错误报告。例如,将下面的声明添加到Employee类中:

@Override public Boolean equals(Employeeother)       //ERROR

就会看到一个错误报告,这是因为这个方法并没有覆盖超类Object类中的任何方法。

 

HashCode方法

散列码(hash code)是由对象导出的一个整型值,散列码是没有规律的。

由于hashCode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址,看一下下面的这个例子:

String s = “OK”;
StringBuilder sb = new StringBuilder(s);
System.out.println(s.hashCode() + “ ”+ sb.hashCode());
String t = “OK”;
StringBuilder tb = new StringBuilder(t);
System.out.println(t.hashCode() + “ “ +tb.hashCode());

输出如下:

Object

HashCode

s

2556

sb

20526976

t

2556

tb

20527144

字符串s和t拥有相同的散列码,这是因为字符串的散列码是由内容导出的。而字符串缓冲sb和tb却有不同的散列码,这是因为在StringBuilder类中没有定义hashCode方法,它的散列码是由Object类的默认hashCode方法导出的对象存储地址。

如果重新定义equals方法,就必须重新定义hashCode方法,以便用户将对象插入到散列表中。

HashCode方法应该返回一个整型数值(也可以是负数),并合理地组合实例域的散列码,以便能够让不同对象产生的散列码更加均匀。

Equals域hashCode的定义必须一致,如果x.equals(y)返回true,那么x.hashCode()就必须与y.hashCode()具有相同的值。例如,如果用定义Employee.equals比较雇员的ID,那么hashCode方法就需要散列ID,而不是雇员的姓名或存储地址。

下面是Employee类的hashCode方法:

class Employee
{
	public int hashCode()
	{
	return 7 * name.hashCode()
		+ 11 * newDouble(salary).hashCode()
		+ 13 *hireDay.hashCode();
	}
	//省略部分代码
}

PS:如果存在数组类型的域,那么使用静态的Arrays.hashCode()方法计算一个散列码,这个散列码有数组元素的散列码组成。

 

ToString方法

在Object中还有一个重要的方法,就是toString方法,它用于返回表示对象值的字符串。

绝大多数(但不是全部)的toString方法都遵循这样的格式:类的名字、随后是一对用方括号括起来的域值。

最好通过getClass().getName()获得类名的字符串,而不要将类名硬加到toString方法中:

public String toString()
{
	return getClass().getName()
		+ “[name=” + name
		+ “,salary=” + salary
		+ “,hireDay=” + hireDay
		+ “]”;
}

toString方法也可以供子类调用。

设计子类的程序员也应该定义自己的toString方法,并将子类域的描述添加进去。如果超类使用了getClass().getName(),那么子类只要调用super.toString()就可以了。

 

随处可见toString方法的主要原因是:只要对象与一个字符串通过操作符“+”连接起来,Java编译器就会自动的调用toString方法,以便获得这个对象的字符串描述。

 

如果x是任意对象,并调用

System.out.println(x);

println方法就会调用x.toString(),并打印输出得到的字符串。

 

Object类定义了toString方法,用来打印输出对象所属的类名和散列码。例如,调用System.out.println(System.out),将输出以下内容:

       java.io.PrintStream@zf6684

之所以得到这样的结果是因为PrintStream类的设计者没有覆盖toString方法。

 

令人烦恼的是,数组继承了Object类的toString方法,数组类型将按照旧的格式打印,例如:

int[] luckyNumbers = {2,3,5,7,11,13};
String s = “” + luckyNumbers;

生成字符串“[I@1a46e30]”(前缀[I表明是一个整数型数组]。修正的方法是调用静态方法Arrays.toString()。代码:

String s = Arrays.toString(luckyNumbers);

将生成字符串“[2,3,5,7,11,13]”。

toString是一种非常有用的调试工具。在标准类库中,许多类都定义了toString方法,以便用户能够获得一些有关对象状态的重要信息。

PS:强烈建议为自定义的每一个类增加一个toString方法。这样做不仅自己收益,而且所有使用这个类的程序员也会受益匪浅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值