[TIL][Java] equals()메소드 vs ==연산자 비교하기

sorzzzzy·2021년 8월 22일
1

TIL

목록 보기
1/36
post-thumbnail

스프링 강의를 들으면서, Enum 타입은 비교연산자로 equals() 대신에 == 를 써도 된다고 배웠는데 이게 무슨 뜻일까.. 싶어서..🤔!

  • 자바에서 일반적인 데이터 타입의 비교는 == 이라는 연산자를 사용하여 비교한다.
  • 그러나 문자열(=String)의 값을 비교할때에는 equals()라는 메소드를 사용하여 비교한다.

단순히 이렇게만 알고 있었지 왜 인지는 크게 궁금해하지 않았던 것 같다,, 반성하고 있다 하하하하 😂
그래서❗️ 이번 기회에 개념을 확실히 잡고 정리해봐야겠다!


🏷 ==

  • == 연산자는 int,boolean과 같은 primitive type에 대해서는 값을 비교한다.
  • reference type에 대해서는 주소값을 비교한다.
    ( 사실 primitive type도 Constant Pool에 있는 특정 상수를 참조하는 것이기 때문에 결국 주소값을 비교하는 것으로 볼 수 있다.)
  • 같은 상수를 참조하면 주소값이 같기 때문에 결국 같은 값이면 동일하다고 판단할 수 있다!

🏷 Equals()

  • equals()는 비교하고자 하는 대상의 값 자체를 비교한다.
  • equals()는 최상위 클래스인 Object에 포함되어 있기 때문에 모든 하위 클래스에서 재정의해서 사용이 가능하다!

⬇️ Object클래스의 equals()의 코드를 살펴보자!

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

⬇️ 이번에는 String 클래스의 equals()를 살펴보자!

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
  • equals()변수로 들어온 객체가 자신과 주소값이 같다면 true를 리턴한다.
  • 만약 주소 값이 다르다면 String 객체의 문자열을 Char타입으로 하나씩 비교해 끝까지 같다면 true를, 다르다면 false를 리턴한다.
    즉, 서로 다른 객체라도 같은 문자열을 가지고 있다면 같다고 판단한다!
  • String 클래스에는 처음부터 equals()문자열을 비교하게 재정의되어 있어서 문자열 비교'도' 가능한 것❗️

🏷 그렇다면 둘의 차이는?

💡 알고 들어가자 💡
문자열(=String)에 값을 할당하는 방법에는 2가지가 있다!
1️⃣ String str = new String("sorzzzzy");
➡️ new 연산자를 이용하는 방식
2️⃣ String str = "sorzzzzy";
➡️ 리터럴를 이용한 방식

  • 위의 두 가지 방식에는 큰 차이가 존재한다.
    리터럴을 사용하게 되면 string constant pool이라는 영역에 존재하게 되고,
    new 연산자를 통해 String을 생성하면 Heap 영역에 존재하게 된다.

🤔 : 도대체 그래서 둘의 차이점이 뭐라는 거야 ❓ 코드를 보며 이해해보자 ❗️

public class test1 {
    public static void main(String[] args) {
        String str1 = "sorzzzzy";
        String str2 = new String("sorzzzzy");
		
        if(str1 == str2) {
            System.out.println("값이 같습니다");
        }else {
            System.out.println("값이 다릅니다");
        }
    }
}

⬆️ 결과는 값이 다릅니다 ❗️
== 연산자는 주소값을 비교한다고 했다!
리터럴을 사용해 string constant pool 영역에 만든 객체와 new 연산자를 통해 heap 영역에 만든 객체는 당연히 주소값이 다를 수 밖에 없다.

public class test2 {
    public static void main(String[] args) {
        String str1 = "sorzzzzy";
        String str2 = new String("sorzzzzy");
		
        if(str1.equals(str2)) {
            System.out.println("값이 같습니다");
        }else {
            System.out.println("값이 다릅니다");
        }
    }
}

⬆️ 결과는 값이 같습니다 ❗️
equals() 메소드는 주소 값이 아닌 값 자체를 비교하기 때문에 객체가 다르더라도 같은 문자열을 가지고 있다면 같다고 판단한다!

💡 즉, ==연산자와 equals()의 가장 큰 차이는 == 연산자는 비교하고자 하는 대상의 주소값을 비교하는 반면, equals() 는 비교하고자 하는 대상의 값 자체를 비교한다❗️
(equals() 도 내부적으로 주소값을 비교하지만 String클래스에서는 equals()재정의해 값을 비교하게 되어있다.)

📌 참고

  • 일반적인(int, char 등) 타입들은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용된다.
  • 그러나 String은 일반적인 타입이 아니라 클래스이므로, 기본적으로 Call by Reference 형태로 생성 시 주소값이 함께 부여된다!
  • 그렇기에 String 타입을 선언했을 때, 같은 값을 부여하더라도 서로간의 주소값이 다를 수가 있는 것이다 !!

참고 자료 1
참고 자료 2

profile
Backend Developer

0개의 댓글