[JAVA] == 비교 연산자, equals() 메서드 , hashCode()

Dayeon myeong·2021년 3월 26일
0

[JAVA]자바 기초

목록 보기
3/3

==과 equals()

  • == : 객체의 주소값을 비교 (call by reference), 같은 값이라도 주소값이 다르면 false가 나온다. 따라서 ==는 int와 같은 primitive type을 비교할 때 사용된다.

  • equals() : 객체끼리 내용 비교 (call by value)


class Main {

    public static void main(String[] args) throws Exception {
        String str1 = "abc";
        String str2 = str1;
        
        String str3 = new String("abc");
        
        System.out.println(str1 == str2); // true,주소 비교,주소가 서로 같으므로(주소를 서로 공유하므로) 
        System.out.println(str1 == str3); // false,주소 비교,각각 생성된 객체이므로 다른 주소를 가진다. 
		
        System.out.println(str1.equals(str2)); //true, equals는 내용 비교, 
        //String에서는 이미 equals가 오버라이드되어있기 때문에 내용비교가 가능하다
        
        
        System.out.println(str1.equals(str3));// true
    
    }
}

객체의 equals()와 ==


class Main {

	static class Obj {
    	int a;
        
        public Obj(int a) {
        	this.a = a;
        }
    }
	
    public static void main(String[] args) throws Exception {
    
    	int a = 2;
        int b = 2;
        
        System.out.println(a == b); // true,primitive type에서의 ==
        Obj aa = new Obj(1);
        Obj bb = new Obj(1);
        
    	System.out.println(aa == bb);// false,주소 비교,다른 객체이므로
        
        System.out.println(aa.equals(bb)); // false, 내용 비교이지만 Obj의 equals()를 재정의하지 않았기 때문에(오버라이드 안함).
       
    
    }
}

aa.equals(b)가 false인 이유는 Obj 클래스에서 equals를 재정의하지 않았기 때문에 상위 클래스인 Object 클래스의 equals()로 동작이 된다.

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

Object의 equals()는 위와 같이 정의가 되며, 주소를 비교하기 때문에 false가 나온 것이다.

그래서 equals로 내용 비교를 하기 위해서는 Obj 클래스에서 euqals()를 재정의해줘야한다.

static class Obj {
    	int a;
        
        public Obj(int a) {
        	this.a = a;
        }

        @Override
      	public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          Obj that = (Obj) o;
          return a == that.a;
      	}

      	@Override
      	public int hashCode() {
          return Objects.hash(a);
      	}
    }
	
	

위와 같이 equals를 재정의한다면 true가 반환된다.

public static void main(String[] args) throws Exception {
    
    	int a = 2;
        int b = 2;
        
        System.out.println(a == b); // primitive type에서의 ==, true
        Obj aa = new Obj(1);
        Obj bb = new Obj(1);
        
    	System.out.println(aa == bb);// 주소 비교,다른 객체이므로 false
        
        System.out.println(aa.equals(bb)); // **true, override 되어있기 때문에 true
    
    }

equals()와 hashCode()

위 코드에서 equals를 재정의할 때 hashCode를 같이 재정의 했다.

equals()와 hashCode()를 같이 재정의 하는 이유는 다음과 같다.

  1. hashCode는 객체의 주소를 int로 변환해서 해쉬코드를 생성한다. 내용이 같으면 같은 객체라고 equals()로 정의했음에도 불구하고, hashCode를 생성시에는 각자의 주소를 가지고 hashCode를 만들게 되어 서로 다른 hasoCode를 가지게 된다.

  2. 1번에서 말했듯이 hashCode를 재정의하지 않으면 같은 값 객체라도 해시코드가 다를 수 있다. 따라서, HashTable과 같은 자바 컬렉션 프레임워크에서는 해당 객체가 저장된 해시 버킷을 찾을 수 없다. 반대로 equals를 재정의하지 않으면 hashCode()가 만든 해시값을 이용해 객체가 저장된 버킷을 찾을 수는 있지만, 해당 객체가 자신과 같은 객체인지 값을 비교할 수 없다.

String에서의 hashCode()

String 클래스의 hashCode는 equals와 같이 오버라이딩 되어 문자열의 내용을 기반으로 해시코드를 생성하기 때문에 문자열의 내용이 같다면, 항상 같은 값의 해시코드를 반환한다.

System.identityHashCode(Object x)

System.identityHashCode(Object x)는 Object 클래스의 hashCode 메서드처럼 객체의 주소값으로 해시코드를 생성하기 때문에 모든 객체에 대해 항상 다른 해시코드값을 반환하는 것이 보장된다.

만약, 두개의 객체가 equals()와 hashCode()를 재정의하여 두 개의 객체가 같다고 했을 경우에 identityHashCode(..)를 사용하면 서로 다른 객체인 것을 알 수 있다.

profile
부족함을 당당히 마주하는 용기

0개의 댓글