본문 바로가기
JAVA

[JAVA] equals 와 == 의 차이(근데 좀 재밌게..)

by 지금갑시다 2024. 2. 10.

 

아주 간단하게 정의하자면!

equals()의 경우에 value값의 비교를 하고, == 의 경우 reference의 비교를 한다!

따라서 문자열의 비교와 같은 경우 value 체크를 해주는 경우가 대부분이라, == 보다는 equals를 사용하는 것이 좋다.

 

reference 비교란, 메모리 상에 위치한 곳이 동일한지, 즉 메모리 주소의 비교를 하는 것이고

value 비교란, 단순히 화면에 보이는 값이 동일함을 비교하는 것이다!

 

 

reference 비교는 대략 메모리를 포인팅하고 있는 값의 비교로 이해할 수 있는데

value의 비교는 어떻게 진행될까? 코드와 함께 확인해보자

 

java.lang.String.equals()

 

java.lang 패키지의 String 클래스에 정의된 equals() 메서드이다.

하나씩 확인해보자.

 

1. if (this == anObject) { }

if문의 경우 비교를 하려는 대상이 this, 즉 나 자신과 동일한 메모리 공간에 있다면, 더 볼 것도 없이 같은 놈이다~ 라고 판단한다.

이 지점에서 == 연산이 훨씬 빠르겠구나?! 예상해 볼 수 있다.

 

2. return anObject instance of String aString

String 타입의 aString을 정의하고, anObject가 String 타입이 맞는지 우선 확인한다.

 

 

3. && (!COMPACT_STRINGS...

 

 COMPACT_STRINGS는 java9부터 적용된 것이라 한다.

UTF16과 같은 UTF형식의 문자열을 저장할때에는 각각의 문자를 2바이트로 표현했다.

그러나 특별히 문자열이 라틴 알파벳 문자로만 이루어졌을때는

COMPACT_STRINGS flag를 활용해 각 문자를 1바이트에 넣어 메모리 최적화가 가능해지게 한다.

 

 신기하게, 현재는 static function으로 true를 기본값으로 갖는다. 따라서, 뒤에 있는 coder에 equals연산을 맡기는 것으로 보인다.

다만!!! 이 값은 JVM에게 inject 받는 값이라고 명시되어 있으므로, 빌드 설정으로 언제든 원하는 값으로 바꿀 수 있다.

 

 

4. this.coder == aString.coder

coder의 설명을 보면, 바이트 코드를 Latin1 혹은 UTF16 형식으로 전환해주는 설정값이고, 이는 VM에 종속적이게 된다. 따라서 같은 VM환경에서 돌아간다면, 이는 항상 True값이 될 것이다. 둘 다 String 이기 때문이다.

 

 

5. StringLatin1.equals(value, aString.value)

우선 각 value들을 각 String의 Character Storage이다. 즉 "abc"라는 문자열이라면, ["a", "b", "c"] 와 유사할 것이다.

그리고 이 두개를 비교하게 되는데, 이는 StringLatin1 클래스를 끌고오기 때문에 어떻게 보면 equals의 역할을 다른 클래스에 넘기는 것이다. StringLatin1 클래스 정의를 보자

StringLatin1.equals()

 

@IntrinsicCandidate의 설명은 아래와 같다.

@IntrinsicCandidate

 

 즉, 해당 어노테이션이 명시된 메서드 혹은 생성자의 경우, VM에서 직접 구현할수 있다는 명시적인 표현이다. 즉 assembly 혹은 컴파일러 레벨에서 최적화를 할 수 있다면, 구현할 수 있다는 것이다.

 아마 "equals() 함수가 for문을 돌며 Linear하게 체크하기 때문에, 이를 향상시켜 구현하고 싶다면 할 수 있다." 라는 표시인 것 같은데,, 아직 제 레벨은 그정도가 아니라,,ㅎㅎ 넘어가야겠다..

 

 

그 아래 if 문부터 for문의 경우

value와 other의 길이비교를 먼저하고, 다르다면 return false!

그 다음으로 value와 other의 각 바이트를 비교하며 체크를 하다가, 틀린부분이 중간에 있다면! return false!!

끝까지 for문이 끝났다면 value와 other가 같은 바이트 구성으로, return true! 를 해주게 된다.

 

이때, 위에서 본 COMPACT_STRINGS의 역할이 있을 수 있다. 문자열 encoding이 UTF16이라면, 각 문자당 2바이트 일 것이고, Latin 문자열로만 이루어져 있다면, 문자당 1바이트일 것이다. 즉 for문을 1/2배 줄일 수 있는 것이다.

 

 

이렇게 1 ~ 5번의 조건을 모두 true로 만족하게 되면, String의 value 값 비교는 마무리가 된다.

이 중 하나라도 false가 나온다면, 두 String은 서로 다른 값을 가지고 있을 것이다!

 

 

끘!!

'JAVA' 카테고리의 다른 글

생각해보게 되는 bit, Byte, int, long 등의 이야기  (1) 2024.02.17