equal 에 대한 깊이 있 는 연구
equals 방법의 중요성 은 더 말 할 필요 가 없다. 네가 비교 하고 싶 은 두 대상 이 같은 대상 이 되 기 를 원 하지 않 는 다 면 너 는 반드시 실현 해 야 한다.
equals 방법, 대상 을 동일 하 다 고 생각 하 는 조건 으로 비교 하도록 합 니 다.
아래 의 내용 은 API 의 규범 일 뿐 그다지 깊 은 의 미 는 없 지만 제 가 가장 먼저 그것 을 여기에 열거 한 이 유 는...
이런 규범 들 은 사실 에서 결코 진정 으로 실현 을 보장 할 수 있 는 것 이 아니다.
1. 모든 인용 유형 에 대해 o. equals (o) = = true 가 성립 됩 니 다.
2. 만약 o. equals (o1) = = true 가 성립 된다 면 o1. equals (o) = = true 도 반드시 성립 되 어야 한다.
3. o. equals (o1) = = true 가 성립 되 고 o. equals (o2) = = true 가 성립 된다 면
o1. equals (o2) = = true 도 성립 됩 니 다.
4. 첫 번 째 호출 o. equals (o1) = = true 성립 재 o 와 o1 이 변 하지 않 은 경우 이후 의 어떠한 호출 도
모두 성립 되다.
5. o. equals (null) = = true 는 어떠한 시간 도 성립 되 지 않 습 니 다.
상기 몇 가지 규칙 은 가장 완전한 표현 이 아 닙 니 다. 상세 한 것 은 API 문 서 를 참조 하 십시오.
Object 류 에 있어 서 가장 엄밀 한 실현 을 제공 합 니 다. 그것 은 바로 같은 대상 만 이 'equals 방법' 이 true 로 돌아 가 는 것 입 니 다. 즉, 사람들 이 흔히 말 하 는 인용 비교 이지 값 비교 가 아 닙 니 다. 이 실현 은 실제 적 인 의미 가 없 을 정도 로 엄밀 하기 때문에 구체 적 인 하위 클래스 (Object 에 비해) 에서 우리 가 대상 의 값 을 비교 하려 면자신의 equals 방법 을 실현 해 야 합 니 다.
먼저 다음 절 차 를 살 펴 보 겠 습 니 다.
public boolean equals(Object obj) { if (obj == null) return false; if (!(obj instanceof FieldPosition)) return false; FieldPosition other = (FieldPosition) obj; if (attribute == null) { if (other.attribute != null) { return false; } } else if (!attribute.equals(other.attribute)) { return false; } return (beginIndex == other.beginIndex && endIndex == other.endIndex && field == other.field); }
이것 은 JDK 에서 자바. text. FieldPosition 의 표준 실현 으로 할 말 이 없 는 것 같 습 니 다.
나 는 대부분의 프로그래머 나 절대 다수의 프로그래머 들 이 이것 이 정확 하고 합 법 적 인 equals 실현 이 라 고 생각한다. 왜냐하면 이것 은 JDK 의 API 실현 이기 때문이다.
사실 로 말 합 시다.
package debug;import java.text.*;public class Test { public static void main(String[] args) { FieldPosition fp = new FieldPosition(10); FieldPosition fp1 = new MyTest(10); System.out.println(fp.equals(fp1)); System.out.println(fp1.equals(fp)); }}class MyTest extends FieldPosition{ int x = 10; public MyTest(int x){ super(x); this.x = x; } public boolean equals(Object o){ if(o==null) return false; if(!(o instanceof MyTest )) return false; return ((MyTest)o).x == this.x; }}
무엇이 인쇄 되 는 지 실행 해 보 세 요.System.out.println(fp.equals(fp1));인쇄 true
System.out.println(fp1.equals(fp));인쇄 flase
두 대상 에 게 비대 칭 equals 알고리즘 이 나 타 났 습 니 다. 문 제 는 어디 에 있 습 니까?
나 는 많은 프로그래머 들 이 equals 방법 을 전혀 모 르 는 프로그래머 들 을 제외 하고 equals 방법 을 실현 하고 있다 고 믿는다.
인 스타 그램 운영 자 를 사용 하여 단락 최 적 화 를 한 적 이 있 습 니 다. 실사구시 적 으로 오랫동안 저도 이렇게 사용 한 적 이 있 습 니 다.
너무 많은 튜 토리 얼 이 우리 에 게 이런 오 도 를 주 었 다.약간 아 는 프로그래머 들 은 이런 최적화 가능성 을 알 수 있다.
좀 틀 렸 지만 문제 의 관건 을 찾 지 못 했다.또 다른 극단 은 이 기술적 결함 을 아 는 유골 급 전문가 가 이 를 원 하지 않 는 다 고 제안 한 것 이다.
견본 응용.
우 리 는 '보통' 이 두 대상 을 비교 해 야 한 다 는 것 을 알 고 있다. 그러면 그들 은 '마 땅 히' 가 같은 유형 이 어야 한다.그래서 우선 인 스 턴 스 of 를 이용 해 요.
실행 부 호 를 단락 최적화 합 니 다. 비교 대상 이 현재 대상 과 같은 유형 이 아니라면 false 로 돌아 가지 않 아 도 됩 니 다. 그러나 사실 입 니 다.
"하위 클래스 는 부모 클래스 의 인 스 턴 스 입 니 다". 따라서 하위 클래스 o instanceof 부모 클래스 가 처음부터 끝까지 true 로 돌아 가면 분명 합 니 다.
단락 최적화 가 발생 하지 않 고 아래 의 비 교 는 여러 가지 상황 이 발생 할 수 있다. 하 나 는 부 류 를 조형 하지 못 하고 이상 을 던 지 는 것 이 고 다른 하 나 는
아버지 류 의 private 멤버 는 이불 류 의 계승 이 없어 비교 할 수 없 으 며, 위의 비대 칭 비 교 를 형성 하 는 것 이다.이 가능 하 다, ~ 할 수 있다,...
너무 많은 상황 이 발생 할 것 이다.
그렇다면 인 스타 그램 운영 자 를 최적화 할 수 없 는 것 일 까?정 답 은 부정 적 이 고, JDK 에 서 는 여전히 많은 실현 이 긍정 적 이다.
확실한 것 은 만약 에 하나의 class 가 final 이 라면 하위 클래스 가 있 을 수 없다 는 것 을 알 면서 왜 instanceof 로 최적화 하지 않 습 니까?
썬 의 개발 팀 의 명 예 를 지 키 기 위해 서 나 는 어떤 유형 중 하 나 를 설명 하지 않 지만, 한 팀 의 구성원 이 이 방법 으로 최적화 할 때 나중에 추가 합 니 다.
이런 주석 을 달 았 습 니 다.
if (this == obj) // quick check return true; if (!(obj instanceof XXXXClass)) // (1) same object? return false;
의문 이 있 었 는 지 어떻게 해 야 할 지 모 르 겠 어 요.그렇다면 비 final 류 에 대해 서 는 어떻게 유형의 quick check 을 진행 합 니까?
if(obj.getClass() != XXXClass.class) return false;
비교 대상 의 클 라 스 대상 과 현재 대상 의 클 라 스 를 비교 하 는 것 은 문제 가 없 는 것 처럼 보이 지만, 이 클래스 의 하위 클래스 가
equals 방법 을 다시 실현 하지 않 았 다 면 하위 클래스 를 비교 할 때 obj. getClass () 는 XXXCalss. class 와 같 지 않 을 것 입 니 다.
즉, 하위 클래스 의 equals 가 올 바 르 지 않 기 때문에 if (obj. getClass ()! = this. getClass () return false;바로
확실한 비교.
equals 방법 이 반드시 비교 해 야 하 는 두 대상 은 반드시 같은 유형 이 어야 합 니까?위 에서 나 는 '보통' 을 사 용 했 는데, 이것 도 절대 다수의 프로그램 이다.
직원 의 소망 이지 만 어떤 특수 한 상황 에서 우 리 는 서로 다른 유형의 비 교 를 할 수 있 는데 이것 은 규범 에 어 긋 나 지 않 는 다.그러나 이런 특수 한 상황 은
매우 보기 드 문 것 입 니 다. 하나의 부적 절 한 예 는 Integer 류 의 equals 가 Sort 와 비교 할 수 있 고 그들의 value 를 비교 할 수 있 습 니 다.
같은 수학 값 입 니 다.(사실 JDK API 에 서 는 그렇게 하지 않 았 기 때문에 부적 절 한 예 라 고 말 하 는 것)
quick check 을 완성 한 후에 우 리 는 당신 이 생각 하 는 '같다' 는 것 을 진정 으로 실현 해 야 합 니 다.실현 대상 이 같다 면 그다지 높 지 않다.
의 요구, 예 를 들 어 당신 이 실현 한 '사람' 류 는 name 이 같 으 면 그들 이 같다 고 생각 하고 다른 sex 라 고 생각 할 수 있 습 니 다.
생각 안 해도 돼.이것 은 완전히 실현 되 지 는 않 지만 완전히 실현 된다 면 모든 속성 이 똑 같 아야 한다.
어떻게 equals 방법 을 실현 합 니까?
class Human{private String name;private int ago;private String sex; .................... public boolean equals(Object obj){quick check.......Human other = (Human)ojb;return this.name.equals(other.name)&& this.ago == ohter.ago&& this.sex.equals(other.sex);}}
이것 은 완전히 실현 되 는 것 이지 만, 때로는 equals 실현 은 아버지 류 에서 이 루어 지 는 것 이 고, 이불 류 의 계승 후 equals 가 정확 한 작업 을 할 수 있 도록 요구한다.이 럴 때 하위 클래스 가 어떤 속성 을 확장 하 는 지 알 지 못 하기 때문에 위의 방법 으로 equals 를 완전히 실현 할 수 없습니다.
좋 은 방법 은 반 사 를 이용 하여 equals 를 완전히 실현 하 는 것 이다.
public boolean equals(Object obj){quick check.......Class c = this.getClass();Filed[] fds = c.getDeclaredFields();for(Filed f:fds){if(!f.get(this).equals(f.get(obj)))return false;}return true;}
설명 의 편 의 를 위해 상명 의 실현 은 이상 을 생략 하 였 습 니 다. 이러한 실현 은 아버지 류 에 두 면 당신 의 하위 클래스 의 equals 가 누 를 수 있 도록 보장 할 수 있 습 니 다.너의 소망 은 정확하게 일한다.
equals 방법 에 대한 마지막 점 은 equals 방법 을 다시 쓰 면 equals 방법 과 동시에
반드시 hashCode () 를 다시 써 야 합 니 다. 규범 이 어야 합 니 다. 그렇지 않 으 면...........................................
우 리 는 이 예 를 살 펴 보 자.
public final class PhoneNumber { private final int areaCode; private final int exchange; private final int extension; public PhoneNumber(int areaCode, int exchange, int extension) { rangeCheck(areaCode, 999, "area code"); rangeCheck(exchange, 99999999, "exchange"); rangeCheck(extension, 9999, "extension"); this.areaCode = areaCode; this.exchange = exchange; this.extension = extension; } private static void rangeCheck(int arg, int max, String name) { if(arg < 0 || arg > max) throw new IllegalArgumentException(name + ": " + arg); } public boolean equals(Object o) { if(o == this) return true; if(!(o instanceof PhoneNumber)) return false; PhoneNumber pn = (PhoneNumber)o; return pn.extension == extension && pn.exchange == exchange && pn.areaCode == areaCode; }}
이 종 류 는 final 이기 때문에 이 equals 실현 에는 문제 가 없습니다.
테스트 해 보 겠 습 니 다.
public static void main(String[] args) { Map hm = new HashMap(); PhoneNumber pn = new PhoneNumber(123, 38942, 230); hm.put(pn, "I love you"); PhoneNumber pn1 = new PhoneNumber(123, 38942, 230); System.out.println(pn); System.out.println("pn.equals(pn1) is " + pn.equals(pn1)); System.out.println(hm.get(pn1)); System.out.println(hm.get(pn)); }
pn. equals (pn1) 라면 넣 겠 습 니 다 (pn, "I love you").후, get (pn1) 이것 은 무엇이 null 입 니까?정 답 은 hashCode 가 다 르 기 때문에 hashMap 은 hashCode 를 메 인 키 로 합 니 다.
따라서 규범 적 인 요 구 는 두 대상 이 equals 를 비교 할 때 true 로 돌아 가면 hashcode 는 같은 값 으로 돌아 가 야 합 니 다.
원본 주소:
http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=121&threadID=17726&tstart=0
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
2022년 3월 21일 TIL1. JVM & JDK JVM JRE 자바 실행 환경의 약자로 자바 프로그램을 실행하기 위한 도구들이 들어있으며 JVM이 이 안에 포함된다 JDK JRE + 개발툴 javac는 컴파일 명령어 HelloWorld.cl...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.