알고리즘 문제를 풀다가 Integer 객체에 대한 정수값을 비교해야 하는 일이 발생했다.
Integer a = 1;
Integer b = 1;
System.out.println(a == b);
출력 값은 true
가 된다.
Wrapping class인 Integer 타입에서 ==
비교는 객체의 주솟값을 비교하는 것인데, 출력 값이 true
가 나오게 되어 당황스러웠다. 그 이유를 알아보기 위해 Integer 객체의 내부 구조를 파헤쳐보았다.
Java에서 정수형을 비교하는 방법은 2가지가 있다. ==
와 equals
==
연산자는 Primitive type에서 값으로 비교하고, Wrapper Class에서는 각 객체의 주소 값으로 비교한다.
equals
메소드는 각 객체 간의 값을 비교할 때 사용된다. 이를 Primitive type인 int 비교에 사용하면 참조할 수 없다고 오류가 발생한다.
그렇다면 다음 예시를 살펴보자.
Integer a = 100;
Integer b = 100;
if (a == b) System.out.println("a and b are the same.");
if (a != b) System.out.println("a and b are different.");
if(a.equals(b)) System.out.println("a and b contain the same value.");
출력값은 다음과 같다.
a and b are the same.
a and b contain the same value.
“a and b are the same.” 의 결과가 나오는 이유는 Java Integer 객체 내부의 Caching에 있다.
Integer 객체 내부에 inner class로 정의되어 있는 IntegerCache 객체를 보면 다음과 같은 구조로 구현되어 있다.
Integer a = 10;
혹은 Integer a = Integer.valueOf(10);
와 같이 선언을 하면, 256개의 Integer 객체가 -128에서 127까지 생성되며 모두 Integer 배열에 저장된다. 위의 이미지를 보면, cache
배열에 저장되는 것을 알 수 있다.
따라서 Integer.valueOf()
를 사용하여 객체를 생성하거나 -128에서 127 범위 내에서 Integer에 직접 값을 할당하면 동일한 객체가 반환된다.
Integer a = 100;
Integer b = 100;
if (a == b) System.out.println("a and b are the same.");
if (a != b) System.out.println("a and b are different.");
if(a.equals(b)) System.out.println("a and b contain the same value.");
그러므로 위 예시에서 a와 b는 -128과 127 범위 내의 값이기 때문에 동일한 객체가 된다. 하지만 a와 b가 -128과 127 범위를 벗어나면 캐시가 사용되지 않으므로 새 객체가 생성된다. 그 때는 equals
메소드를 사용해서 값을 비교해야 한다.
Integer Wrapping class에서 ==
연산자로 비교를 하는 경우에는 -128 ~ 127 사이의 값을 제외하고는 원하지 않은 결과가 발생할 수 있다. 고로 객체를 비교할 때는 equals()
메소드를 사용해서 비교를 하는 것이 좋을 것 같다.ㅋ