본문 바로가기
Web Technologies 🖥️/java

equals() 랑 "==" 랑 똑같은 거 아니였어? - JAVA

by dudefromkorea 2023. 12. 17.

String 변수를 선언하는 방법이

두 가지가 있다는 사실을 아시나요?

 

흔히(?) 사용한다고 할 수 있는

리터럴을 이용한 방식

String str = "string";

 그리고 new 연산자를 이용한 방식

String str = new String("string");

 

두 방식에는 명백한 차이점이 존재한다

 

new 연산자를 사용하여 선언할 경우

Heap 영역에 존재하게 되고,

 

리터럴을 사용하여 선언할 경우

내부적으로  String 의 intern() 메소드가 호출되고

해당 문자열이 string constant pool 에 존재하는지 확인하고

존재하면 해당 주소값을 반환하고 존재하지 않는다면

string constant pool 에 넣고 새로운 주소 값을 반환한다

 

기본적인 String 생성 방식에

대해서 알아봤으니,

이제는 타입들에 대해서

한 번 살펴보자

 

원시 타입(Primitive Type)

기본 자료형(int, char, float, etc...)의 경우

Call by Value 형태로 대상에

주소값을 가지지 않는 형태로 사용되나

 

참조 타입(Reference Type)

String 은 하나의 클래스이기 때문에

 Call by Reference 형태로

객체 생성 시 주소값이 부여된다

(String, Integer, etc...)

따라서 동일한 문자열을 선언하더라도

다른 주소값을 가지게 된다

 

 

설명을 더 이어나가기 전에

코드를 한 번 살펴보자

"==" vs equals()

public class StringTest {
	public static void main(String args[]) {

		String strConstantPool = "String";
		String strHeap = new String("String");
		
		System.out.println(strConstantPool == strHeap); // false
		System.out.println(strConstantPool.equals(strHeap)); // true
	}
}

 

동일한 문자열을 선언했으나

결과 값이 다른 것을 확인할 수 있다

이유가 대체 뭐일까?

 

먼저 "==" 연산자의 경우에는

객체의 주소값을 비교한다!

 

원시 타입(Primitive Type) 일 경우

Constant Pool 내에서

같은 주소를 비교하기에

겉으로 보기에 값을

비교하는 것처럼 보이지만,

참조 타입(Reference Type) 일 경우

객체의 주소를 비교하게 된다

 

만약 원시 타입과 참조 타입을 비교할 경우

원시 타입의 값과 객체의 주소를

비교하는 것은 의미상으로 올바르지 않기에

자바는 자동으로 타입 불일치 에러를 뱉는다

따라서 결과 값으로 false 가 나오는 것이다

(예외 경우: 자바의 자동 박싱)

 

그럼 equals()는 어떻게

비교하길래 true 가 나온 것일까?

 

equals()는 좀 더 복잡한 로직을 가지고 있다

먼저 1.두 개의 문자열의 주소를 확인한다

만약 같다면 바로 true 를 반환하고,

다르다면 그다음으로 2.타입을 확인한다

String 클래스의 인스턴스가 아닐 경우

false 를 반환하고 인스턴스일 경우

다음으로 3.두 개의 문자열의 내용을 비교한다

이때 각 char 를 하나씩 순차적으로 비교하며

모든 char 가 동일하다면 true,

하나라도 다르다면  false를 반환한다

 

보다시피 Java 에서 equals() 는

문자열의 내용의 동일 여부를

정확하게 비교하기 위해 설계되었으며

"=="와는 다르게 true 가 나오는 이유이다

 

결론

앞으로 JAVA 에서는 String 을 비교할 때

equals() 를 사용하도록 하자!

728x90
반응형