프로그래밍/JAVA

java 연산자 ==, equals(), hashCode() 정리

p-a-r-k 2020. 3. 10. 16:40
반응형

== 연산자

피연산자가 primitive type일 때는 이 같은지 비교하고, 그 외 타입에서는 주소를 비교한다.

public class Test {
    public static void main(String[] ar) {
        // primitive type 비교
        char c1 = 'a';
        char c2 = 'a';
        System.out.println(c1 == c2); // true
        
        // string 타입 리터럴 비교
        String str1 = "park";
        String str2 = "park";
        System.out.println(str1 == str2); // true
        
        // 스트링 생성자객체 비교
        String str3 = new String("park");
        String str4 = new String("park");
        String str5 = str4;
        System.out.println(str3 == str4); // false
        System.out.println(str4 == str5); // true
    }
}

 

변수 c1과 c2는 primitive type이기 때문에 a라는 값으로 비교하였을 때 비교시 true를 확인할 수 있다.

String type 은 primitive type은 아니지만 리터럴표현이 가능하므로 비교해 보았을 때 true를 확인할 수 있다.

new String()으로 생성자를 이용하여 생성 시 false를 확인할 수 있는데,

각각의 메모리에 park라는 String을 만들었다고 볼 수 있기때문에 서로 주소가 다르다고 볼 수 있다.

str4, str5는 str5가 str4의 주소를 바라보고 있기때문에 같은 주소를 가리키므로 true를 return 한다.

 

정리하면, ==연산자는 각각의 객체가 같은 주소를 가리킬 때만 true를 얻을 수 있다.


equals()

equals()는 내용이 같은지를 비교한다.

기본적으로 primitive type은 값을 비교하고, reference type은 주소를 비교한다.

Object 클래스의 메서드이기때문에 모든 객체는 equals()를 사용할 수 있다.

public class TestEquals {
    public static void main(String[] ar) {
        // string 타입 리터럴 비교
        String str1 = "park";
        String str2 = "park";
        System.out.println(str1.equals(str2)); // true

        // 스트링 생성자객체 비교
        String str3 = new String("park");
        String str4 = new String("park");
        String str5 = str4;
        System.out.println(str3.equals(str4)); // true
        System.out.println(str4.equals(str5)); // true
    }
}

 

String객체로만 테스트를 해볼 때 일단 park라는 값들로만 생상이 되어서

str3, str4의 경우 주소는 다르지만 모두 true를 return 한다.

String이 아닌 직접만든 객체의 경우에는 위처럼 자바가 알아서 판단해주지 않는다.

 

public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

 

User이라는 name과 age 속성을 가진 직접 작성한 클래스를 만든 후 ==equals()를 테스트 해보면,

public class TestEquals {
    public static void main(String[] ar) {
        User p1 = new User("park", 19);
        User p2 = new User("park", 19);

        System.out.println(p1 == p2); // false
        System.out.println(p1.equals(p2)); // false
    }
}

 

모두 false를 return한다.

==은 p1, p2가 다른 주소를 바라보기때문에 false를 return 받는다.

하지만 동일한 name과 age를 넘긴경우 equals()는 동일하다고 판단하지 못한다.

java에서는 name만 같으면될지 age까지 같아야 같은건지 판단하지 못하기때문이다.

equals()를 User class에 오버라이드 한다.

IntelliJ에서 generate equals() and hashCode()로 생성해주었다.

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    User user = (User) o;
    return age == user.age &&
            Objects.equals(name, user.name);
}
User p1 = new User("park", 19);
User p2 = new User("park", 19);

System.out.println(p1 == p2); // false
System.out.println(p1.equals(p2)); // true

 

이제 equals()가 true를 return 해준다,,

단, IntelliJ에서 hashCode()까지 같이 generate 해주었지만

equals()만 재 정의시에는 hash를 사용하는 Collection ex) HashSet, HashMap에 넣을경우에는,

hash값이 다르게 되어서 문제가 발생할 수 있다.

아래는 generate된 hashCode()를 주석처리 후 실행한 결과이다.

public static void main(String[] ar) {
    Set h1 = new HashSet<>();
    User p1 = new User("park", 19);
    User p2 = new User("park", 19);
    System.out.println("user1 : "+ p1.hashCode()); // 2018699554
    System.out.println("user2 : "+ p2.hashCode()); // 1311053135
    System.out.println(p1.equals(p2)); // true
    h1.add(p1);
    h1.add(p2);
    System.out.println(h1.size()); // 2
}

 

중복을 자동으로 없애주는 Set에 add시켰는데도 size() 결과가 2가 나온것을 확인할 수 있다,,

* equals로 같은 객체라면 반드시 hashCode로도 같은 값이어야 한다.

아래는 hashCode() 주석 해제 후 결과이다.

Set h1 = new HashSet<>();
User p1 = new User("park", 19);
User p2 = new User("park", 19);
System.out.println("user1 : "+ p1.hashCode()); // 106437930
System.out.println("user2 : "+ p2.hashCode()); // 106437930
System.out.println(p1.equals(p2)); // true
h1.add(p1);
h1.add(p2);
System.out.println(h1.size()); // 1

 


hashCode()

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

 

hashCode()는 메모리에서 가진 hash주소 값을 기본적으로 반환해준다.

반응형

'프로그래밍 > JAVA' 카테고리의 다른 글

java Collection - Queue 정리  (0) 2020.03.10
java Collection - Set 정리  (0) 2020.03.10
java Collection - List 정리  (0) 2020.03.10
java 컬렉션 프레임워크(Collection Framework)  (0) 2020.03.10
java 기초 문법 정리  (0) 2018.05.10