大家好,这是我在CSDN上的第一篇博客,请多关照。
最近在写业务侧代码时,遇到了一个我们在平时编写代码时经常遇到的问题,即:将多个不同的对象放在一个List数组中,再添加对象的过程中,我们会用到contains方法来过滤掉相同的对象(过滤string类型大家都知道,equals比较的是字符串)。
创建一个MailSenderFactory对象
public class MailSenderFactory {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/*@Override
public boolean equals(Object obj)
{
if (obj instanceof MailSenderFactory)
{
MailSenderFactory mail = (MailSenderFactory) obj;
if (mail.getName().equals(this.name) && mail.getId().equals(this.id))
{
return true;
}
}
return false;
}*/
}
上一段测试代码:
public class Test {
public static void main(String[] args)
{
List<MailSenderFactory> mailList = new ArrayList<MailSenderFactory>();
MailSenderFactory mail1 = new MailSenderFactory();
MailSenderFactory mail2 = new MailSenderFactory();
mail1.setId("1");
mail1.setName("wdw");
mail2.setId("1");
mail2.setName("wdw");
mailList.add(mail1);
System.out.println(mailList.contains(mail1));
System.out.println(mailList.contains(mail2));
System.out.println("obj" + System.identityHashCode(mail1));
System.out.println("obj" + System.identityHashCode(mail2));
}
}
输出结果是:
发现定义的mail1和mail2对象属性是一样的,那么认为这两个对象在业务侧是同一个对象,但是第二段输出却是false,说明比较的不是对象的属性,那是什么呢?
我们跟进contains的源码会发现ArrayList.class的公共方法中是如何实现contains的:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Object.equals()
public boolean equals(Object obj) {
return (this == obj);
}
好了,发现了什么?这里调用的equals是Obeject.class中的equals,比较的竟然是对象的引用,更准确讲,比较的是对象的内存地址****
而我也将创建的两个对象的地址打印出来,发现确实不相同。
因此要想按照我们的业务逻辑去过滤相同的对象,必须要对equals方法进行重写,即第一块代码注释掉的部分,
我们再来看下List<Sting>
的equals,调用的是String.class的equals方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
发现比较的是字符串了。
如果发现哪里存在错误或是不准确的地方,请大家指正。
下一篇准备写Set.contains(Object)的用法,希望大家多多关注!