PS/자주 하는 답변

Integer끼리는 반드시 equals로 비교해야 합니다.

djm03178 2023. 1. 6. 11:28

Java에서 자주 보이는, 무한 디버깅을 유발하는 사례입니다. 작은 케이스에서 아무리 해도 반례가 안 나오기 때문에 고생하게 되는 경우가 많습니다.

 

Integer는 primitive type 인 int를 객체의 형태로 편하게 표현하기 위한 wrapper 클래스입니다. primitive type은 Object로서 다룰 수 없기 때문에 언어 차원에서 특별히 이러한 클래스를 제공해주는데, Integer와 int 사이의 형변환이 자동으로 이루어지기 때문에 둘을 같은 것처럼 쓰더라도 보통은 문제가 생기지 않습니다...

 

...만, 각별히 신경써야 할 부분이 하나 있는데, 바로 Integer 객체끼리 비교를 해야 하는 경우입니다. 다음의 케이스를 확인해 봅시다. https://ideone.com/XjogFw

public class Main
{
	public static void main (String[] args)
	{
		Integer a = 1, b = 1;
		Integer c = 127, d = 127;
		Integer x = 128, y = 128;
		System.out.println(a == b);
		System.out.println(c == d);
		System.out.println(x == y);
	}
}

이 코드를 실행한 결과는 다음과 같습니다.

true
true
false

오잉...? 이게 대체 무슨 일일까요? 분명히 x와 y에 같은 값 128을 넣었는데 ==으로 비교한 결과가 false가 나옵니다. 1이나 127로 했을 때에는 true가 나왔는데 말이죠.

 

이는 Integer 객체끼리의 비교도 기본적으로 객체끼리의 비교이기 때문에 그렇습니다. 두 객체가 ==이라는 것은 두 객체가 가리키는 몸체 자체가 동일한 한몸이라는 뜻입니다. 서로 다른 두 객체를 new로 각자 만들었다면, 두 객체에 동일한 '값'을 넣더라도 두 객체의 몸체는 서로 다르기 때문에 한쪽의 값을 바꾸어도 다른 쪽에 영향을 주지 않습니다.

 

이는 Integer도 마찬가지입니다. 두 개의 Integer에 값을 각각 넣으면 기본적으로 둘은 다른 객체입니다. 그런데 예외적으로, -128부터 127까지의 Integer 객체는 JVM 차원에서 처음에 미리 만들어두고 시작하고, 이 범위의 Integer를 만들 시에는 새로운 객체를 생성하지 않고 이 미리 만들어진 객체를 대신 돌려줍니다. 그래서 -128부터 127까지의 Integer는 서로 따로 만들었다고 해도 실제로 몸체가 같기 때문에 ==으로 비교했을 때 true가 나오지만, 그 밖의 범위에 대해서는 false가 나오게 됩니다.

 

결론은 Integer끼리의 값 비교를 하기 위해 ==을 쓰면 안 된다는 것입니다. 비교는 항상 equals() 메서드를 통해 해야 합니다. 이 글에서는 Integer를 가지고 설명했지만, 다른 종류의 wrapper 클래스들에 대해서도 모두 마찬가지입니다.