>  기사  >  Java  >  Java 개선 기사----equals() 메소드 요약

Java 개선 기사----equals() 메소드 요약

黄舟
黄舟원래의
2017-02-07 16:48:401220검색

equals()

Object 상위 클래스에는 equals() 메소드가 있습니다. 이 메소드는 주로 두 객체가 동일한지 비교하는 데 사용됩니다. 이 메소드의 소스코드는 다음과 같습니다.

public boolean equals(Object obj) {    return (this == obj);
    }

모든 객체에는 식별(메모리 주소)과 상태(데이터)가 있다는 것을 알고 있으며, "=="는 두 객체의 메모리 주소를 비교하므로 다음과 같이 사용합니다. Object equals() 메소드는 두 객체의 메모리 주소가 동일한지 비교합니다. 즉, object1.equals(object2)가 true이면 equals1과 equals2가 실제로 동일한 객체를 참조한다는 의미입니다. 때로는 Object의 equals() 메소드가 우리의 기본 요구 사항 중 일부를 충족할 수 있지만, 대부분의 경우 두 객체를 비교하는 경우 Object의 equals() 메소드를 사용할 수 없다는 점을 알아야 합니다. 이전 JDK에서는 String 및 Math와 같은 캡슐화 클래스가 equals() 메서드를 다시 작성했습니다.

다음은 String의 equals() 메서드입니다.

public boolean equals(Object anObject) {    if (this == anObject) {        return true;
    }    if (anObject instanceof String) {
        String anotherString = (String)anObject;        
        int n = count;        
        if (n == anotherString.count) {        
        char v1[] = value;        
        char v2[] = anotherString.value;        
        int i = offset;        
        int j = anotherString.offset;        
        while (n-- != 0) {            
        if (v1[i++] != v2[j++])            
        return false;
        }       
         return true;
        }
    }    return false;
    }

이 코드 세그먼트의 경우: if (v1[i++] != v2[j++]) return false를 매우 명확하게 볼 수 있습니다. String의 equals() 메소드는 참조 비교가 아닌 내용 비교를 수행합니다. 다른 캡슐화 클래스도 비슷합니다.

Java 사양에서 equals() 메서드 사용은 다음 규칙을 따라야 합니다.


equals 메서드는 null이 아닌 개체에 있습니다. 참조 동등 관계 실현:

1. 재귀성: null이 아닌 참조 값 x에 대해 x.equals(x)는 true를 반환해야 합니다.

2. 대칭: null이 아닌 참조 값 x 및 y의 경우 y.equals(x)가 true를 반환하는 경우에만 x.equals(y)가 true를 반환해야 합니다.

3. Null이 아닌 참조 값 x, y 및 z에 대해 x.equals(y)가 true를 반환하고 y.equals(z)가 true를 반환하면 x.equals(z ) true를 반환해야 합니다.

4. 일관성: null이 아닌 참조 값 x 및 y의 경우 x.equals(y)를 여러 번 호출하면 항상 true를 반환하거나 항상 false를 반환합니다. 개체가 개정되지 않았습니다.

5. null이 아닌 참조 값 x의 경우 x.equals(null)은 false를 반환해야 합니다.

위의 규칙은 사용 중에 준수하는 것이 가장 좋습니다. 그렇지 않으면 예상치 못한 오류가 발생합니다.

Java에서 비교하려면 비교 유형에 따라 적절한 비교 방법을 선택해야 합니다.


1) 개체 필드에서 방법과 동일합니다.
2) 유형이 안전한 열거형, 같음 또는 ==를 사용합니다.
3) null 개체 필드일 수 있음: == 및 같음을 사용하세요.
4) 배열 필드: Arrays.equals를 사용합니다.
5) float 및 double을 제외한 기본 데이터 유형: ==를 사용합니다.
6) Float 유형: Float.foatToIntBits를 사용하여 int 유형으로 변환한 후 ==를 사용합니다.
7) Double 유형: Double.doubleToLongBit를 사용하여 Long 유형으로 변환한 후 ==를 사용합니다.


6)과 7)을 변환해야 하는 이유는 해당 캡슐화 클래스의 equals() 메서드를 참조하면 됩니다. Float 클래스:

public boolean equals(Object obj) {    return (obj instanceof Float)
           && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
    }

이유는 두 가지 사항이 언급되었기 때문입니다:

However, there are two exceptions:If f1 and f2 both representFloat.NaN, then the equals method returnstrue, 
even though Float.NaN==Float.NaNhas the value false.If <code>f1 represents +0.0f whilef2 represents -0.0f, or vice
versa, the equal test has the valuefalse, even though 0.0f==-0.0f
has the value true.

유형 판단을 위해 equals()에서 getClass를 사용하세요

equals() 메소드를 재정의할 때 , 일반적으로 유형 판단을 위해 instanceof 대신 getClass를 사용하는 것이 좋습니다. 우리 모두는 왼쪽에 있는 객체가 오른쪽에 있는 클래스의 인스턴스인지 여부를 확인하고 부울 유형의 데이터를 반환하는 것이 instanceof의 기능이라는 것을 알고 있습니다. 상속의 하위 클래스 인스턴스가 상위 클래스의 구현인지 여부를 확인하는 데 사용할 수 있습니다. 다음 문장에 주의하세요. 상속의 하위 클래스 인스턴스가 상위 클래스의 구현인지 확인하는 데 사용할 수 있습니다. 문제를 일으키는 것은 바로 이 문장입니다. 먼저 다음 예제를 살펴보겠습니다("고품질 코드: Java 프로그램 개선을 위한 151가지 제안"에서 발췌).

상위 클래스: Person

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;
    }
}

하위 클래스: Employee

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 false;
    }
}

위의 상위 클래스 Person과 하위 클래스 Employee는 모두 동일()을 다시 작성하지만 상위보다 Employee가 더 많습니다. class id 속성입니다. 테스트 프로그램은 다음과 같습니다.

public class Test {    public static void main(String[] args) {
        Employee e1 = new Employee("chenssy", 23);
        Employee e2 = new Employee("chenssy", 24);
        Person p1 = new Person("chenssy");
        
        System.out.println(p1.equals(e1));
        System.out.println(p1.equals(e2));
        System.out.println(e1.equals(e2));
    }
}

위에서는 두 명의 직원과 일반인을 정의합니다. 비록 이름은 같지만 확실히 동일인은 아니므로 논리적으로 출력 결과는 모두 거짓이어야 하지만. 기대와는 달리 결과는 참, 참, 거짓입니다.


이름뿐만 아니라 ID도 비교해야 하기 때문에 e1!=e2라는 것을 이해하는 것은 매우 쉽습니다. 그러나 p1은 e1과 e2와 동일합니다. e1과 e2는 분명히 서로 다른 두 클래스이기 때문에 이것은 매우 이상합니다. 그런데 왜 이런 일이 발생합니까? 먼저 p1.equals(e1)은 p1의 equals 메소드를 호출합니다. 이 메소드는 e1이 Person 클래스인지 확인하기 위해 인스턴스를 사용합니다. 여기서는 왼쪽 객체가 클래스의 인스턴스인지 확인합니다. 오른쪽에서는 상속의 하위 클래스 인스턴스가 상위 클래스의 구현인지 확인하는 데에도 사용할 수 있습니다. 그들 사이에는 상속 관계가 있으므로 반드시 true를 반환할 것이고, 이름도 동일하므로 결과는 확실히 true일 것입니다.


그래서 위와 같은 상황은 "악용"이 매우 쉬운 키워드인 instanceof를 사용했기 때문에 발생합니다. 따라서 같음을 재정의할 때 유형 판단을 위해 getClass를 사용하는 것이 좋습니다. 대신에 instanceof를 사용하세요.


이상은 Java 개선글 - Equals() 메소드의 요약입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요. )!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.