오늘의 나보다 성장한 내일의 나를 위해…
Integer의 ==와 .equals()
코딩 테스트를 공부하는 도중에 이해할 수 없는 일이 발생했다.
Integer의 동등 비교를 하는 if문에서 발생한 문제였는데 말로 설명하는 것보단 코드로 보는 것이 나을 것 같다.
참고로 아래 코드는 코딩 테스트 문제와는 관련이 없다.
HashMap<Integer, Integer> hs=new HashMap<>();
hs.put(5, 2500);
hs.put(1, 2500);
Integer aa = 2500;
Integer bb = 2500;
Integer cc = 3;
Integer dd = 3;
int aaa=3;
Integer bbb=3;
int aaaa=2500;
int bbbb=2500;
System.out.println(hs.get(5) == hs.get(1));
System.out.println(aa == bb);
System.out.println(cc == dd);
System.out.println(aaa == bbb);
System.out.println(aaaa == bbbb);
//결과
false
false
true
true
true
결과에서 이상한 점을 찾았는가?
사실 HashMap은 그냥 헷갈리라고 넣어봤다. 사실상 aa==bb한 것과 같다.
중요한 것은 aa==bb에서 false가 나온 것과 cc==dd에서 true가 나온 것이 헷갈린다.
우리가 기본적으로 ==연산은 주소를 비교하는 것으로 알고 있다.
Integer은 Wrapper Class니까 즉, 객체니까 주소를 비교한다.
그러니까 aa==bb가 false가 나오는 것이 납득이 간다.
하지만! 왜 cc==dd는 true일까?!!
이것도 분명 주소 비교를 할 텐데 말이다. true라는 것은 주소가 같다는 의미가 아닌가?..
해답은 바로 Java Integer 객체의 내부 Caching에 있다.
Java Wrapper Class Cahching 코드를 살펴보면 다음과 같은 구조로 구현되어 있다.
private static class IntegerCache
{
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static
{
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
public static Integer valueOf(int i)
{
final int offset = 128;
if (i >= -128 && i <= 127) // must cache
{
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
즉, -128부터 127에 해당하는 정수값까지는 내부 캐시에 저장되어 있기 때문에 ==연산자로 비교를 해도 int 자료형과 마찬가지의 결과를 얻을 수 있지만 범위를 벗어나는 값들에 대해서는 false 값을 반환한다.
그렇다면 aaa==bbbb는 왜 true가 나오는 것일까?
그것은 바로 Primitive type과 Wrapper Class 사이의 값이 비교되기 때문이다. Primitive type의 경우 == 연산자는 값을 비교한다.
만약 비교 대상 중에 Primitive Type의 변수가 하나라도 있다면 == 연산자는 값으로 비교한다!
즉 Primitive Type인 aaa와 Wrapper Class인 bbb는 값으로 비교하게 되는 것이다.
결론
이런 것을 하나하나 다 기억하기는 어렵다.
중요한 것은 Wrapper Class을 사용해서 값 동등을 할 때는 equals() 메서드를 사용하는 것이 중요하다.