Need to pay attention when the Detailed List contains () method and override the equals () method

Article excerpt from http://blog.csdn.net/javazejian/article/details/51348320

We take a look inside contains methods to achieve

@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}
进入indexof方法

@Override
public int the indexOf (Object o) {
E [] = A this.a;
// null when o is also the return position set when the null
IF (o == null) {
for (int I = 0; I <a.length; I ++)
IF (a [I] == null)
return I;
} the else {
// the indexOf (), the incoming call is actually contains (Object o) equals method argument
for ( 0 = I int; I <a.length; I ++)
IF (o.equals (A [I]))
return I;
}
return -1;
in general we do not override equals () method, then it will call inherited from the object class equals () method, and we all know the object of equals () method, is actually == follows

Boolean the equals public (Object obj) {
return (the this == obj);
}
comparison is whether the same object. So then call contains () method, is to see whether it is actually the same object, but if you override the contains (Object o) the parameter of equals () method, it will produce different results.

And we all know, if you override the equals method, it is necessary to follow these rules:

Reflexivity. x, x.equals (x) should return true for any non-null reference value.

symmetry. Return true, x.equals (y) returns true only y.equals (x): any non-null reference values ​​x and y, iff for.

Transitive. For any non-null reference values ​​x, y and z, if y.equals (x) Returns true, y.equals (z) returns true, then x.equals (z) should return true.

consistency. For any non-null reference values ​​x and y, the comparison information equals assumed object has not been modified, multiple calls x.equals (y) always returns true or always returns false.

For any reference value x, x.equal (null) should return false.

Below is an example:

import java.util.ArrayList;
import java.util.List;

{class AbnormalResult public
public static void main (String [] args) {
List List the ArrayList new new = ();
A = A new new A ();
B = B new new B ();
List.add (A);
the System.out. the println ( "list.contains (A) ->" + list.contains (A));
System.out.println ( "list.contains (B) ->" + list.contains (B));
list.clear ( );
List.add (B);
System.out.println ( "list.contains (A) ->" + list.contains (A));
System.out.println ( "list.contains (B) ->" list.contains + (B));
}
// we streamline internal static class codes, we can see that the equals method to rewrite elements inserted in List, so that when a call to contains, will follow our equals The method of operating
static class A {
@Override
public Boolean the equals (Object obj) {
return the instanceof obj A;
}
}
Static class A {B the extends
@Override
public Boolean the equals (Object obj) {
return the instanceof obj B;
}
}
}
We can see that the output is:

list.contains(a)->true

list.contains(b)->false

list.contains(a)->true

list.contains(b)->true

Apparently this is no problem, but if we only look at this equals method will find that it violates the principle of symmetry rewrite equals () method, since four contains () method call above, equals the actual call ( ) methods are as follows:

①a.equals (a) -> true; // because we only insert an element, so that in comparison with the insertion of this element, the same below

②b.equals(a)->false;

③a.equals(b)->true;

④b.equals(b)->true;

②③ can see the result of the comparison is different, and this violates the principle of symmetry. So, when are you going to rewrite contains () method equals () rule, be sure to check clear whether compliance with the above principle, be verified before use.

The above code is changed as follows, it will return true

the extends class B {A static
@Override
public Boolean the equals (Object obj) {
IF (the instanceof B obj) {
return to true;
}
return super.equals (obj);
}
}
but in practice this method would violate the principle of transfer, The following example of such a

//父类
public class Person {
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name){
this.name = name;
}
public boolean equals(Object object){
if(object instanceof Person){
Person p = (Person) object;
if(p.getName() == null || name == null){
return false;
}
else{
return name.equalsIgnoreCase(p.getName ());
}
}
return false;
}
}
//子类
public class Employee extends Person{
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Employee(String name,int id){
super(name);
this.id = id;
}
/**
* 重写equals()方法
*/
public boolean equals(Object object){
if(object instanceof Employee){
Employee e = (Employee) object;
return super.equals(object) && e.getId() == id;
}
return super.equals(object);
}
//测试代码
public class Test {
public static void main(String[] args) {
Employee e1 = new Employee(“chenssy”, 23);
New new E2 = the Employee the Employee ( "chenssy", 24);
the Person P1 = the Person new new ( "chenssy");
System.out.println (p1.equals (E1));
System.out.println (p1.equals (E2) );
System.out.println (e1.equals (e2));
}
}
according to the principle of the transfer, e1.equals (e2) should return true, but the actual result is false, for that e1 = e2 we are very easy to understand! because they not only need to compare the name, but also need to compare ID. But that is equal to p1 e1 is also equal to e2, which is very strange, because e1, e2 are obviously two different classes, but why would this happen? First p1.equals (e1), is equals method call p1, the method using instanceof keyword e1 to check whether the Person class, where we look at instanceof: to determine whether the object for instance the left to the right class, you can also used to determine whether the implementation instance of a subclass inherits the parent class. They exist both inheritance, and will definitely return true, while both the name and the same, so the result is certainly true. Therefore, the above situation is to use the keyword instanceof, it is very easily lead us "into a dead end." When it is recommended to use getClass override equals the type determination. Instead of using instanceof (unless a subclass with a unified semantic)

Since getClass () is a method of determining whether a class is the same, but the instanceof () determines whether or not inheritance relationship, if above the equals (), inside the instanceof () replaced object.getClass () == Employee.class, not there will be these problems, because returns false.

Author: shenqueying
Source: CSDN
Original: https://blog.csdn.net/shenqueying/article/details/80073140
Copyright: This article is a blogger original article, reproduced, please attach Bowen link!

Guess you like

Origin blog.csdn.net/sjn0815/article/details/91956269