예전에 알고리즘을 푸는 도중, String 변수를 무심코 == 연산자를 사용해 비교해 동작하지 않았던 경험이 있다. 물론 equals() 함수를 사용하니 잘 동작했는데, 그동안 이 둘의 차이가 뭔지 정확히 이해하고 있지 않았던 것 같아서 정리하려고 한다.
Java에서는 int와 boolean과 같은 일반적인 데이터 타입의 비교는 == 연산자를 사용해서 비교한다. 하지만 String같이 Class의 값을 비교할 때는 == 가 아닌 equals()라는 메소드를 사용하여 비교를 해야한다. 이 둘의 차이는 뭘까?
String 변수 생성 시 주소할당
String 변수를 생성할 때는 두가지 방법이 있다.
- 리터럴을 이용한 방식
- new 연산자를 이용한 방식
위 두 가지 방식에는 큰 차이점이 있는데, 리터럴을 사용하게 되면 string constant pool이라는 영역에 존재하게 되고, new를 통해 String을 생성하면 Heap 영역에 존재하게 된다.
String을 리터럴로 선언한 경우, 내부적으로 String의 intern() 메서드가 호출되게 되고, 주어진 문자열이 string constant pool에 존재하는지 검색, 존재한다면 그 주소값을 반환하고 없다면 string constant pool에 넣고 새로운 주소값을 반환한다
String str1 = "apple"; //리터럴을 이용한 방식
String str2 = "apple"; //리터럴을 이용한 방식
String str3 = new String("example"); //new 연산자를 이용한 방식
String str4 = new String("example"); //new 연산자를 이용한 방식
주소값 비교(==)와 값 비교(equals)
==연산자와 equals()메소드의 가장 큰 차이점은 아래와 같다.
== 연산자 | 비교하고자 하는 두개의 대상의 주소값을 비교 |
equals() 연산자 | 비교하고자 하는 두개의 대상의 값 자체를 비교 |
기본 타입의 int형, char형등은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용되지만 String은 일반적인 타입이 아니라 클래스이다. 클래스는 기본적으로 Call by Reference형태로 생성 시 주소값이 부여되기 때문에 String 타입을 선언했을때는 같은 값을 부여하더라도 서로 간의 주소값이 다르다.
문자열 비교
public class compare {
public static void main(String[] args) {
String s1 = "abcd";
String s2 = new String("abcd");
if(s1 == s2) {
System.out.println("== 연산자 => 두 개의 값 같음");
}else {
System.out.println("== 연산자 => 두 개의 값 같지 않음");
}
if(s1.equals(s2)) {
System.out.println("equals() 연산자 => 두 개의 값 같음");
}else {
System.out.println("equals() 연산자 => 두 개의 값 같지 않음");
}
}
}
출력 결과는 다음과 같다.
// == 연산자 => 두 개의 값 같지 않음
// equals() 연산자 => 두 개의 값 같음
'JAVA' 카테고리의 다른 글
[Java] int와 Integer의 차이 (0) | 2022.09.02 |
---|---|
[Java] 스택(Stack)과 큐(Queue) Java로 구현하기 (0) | 2022.02.27 |
[JAVA] static(정적) 변수와 메소드 (1) | 2022.01.13 |