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 클래스들에 대해서도 모두 마찬가지입니다.
'PS > 자주 하는 답변' 카테고리의 다른 글
PyPy3로 제출하면 통과됩니다. (0) | 2023.01.11 |
---|---|
100%에서 틀리는 것의 의미 (0) | 2023.01.07 |
float는 너무나 부정확합니다. (2) | 2023.01.04 |
fflush(stdin), rewind(stdin)은 표준이 아닙니다. (0) | 2023.01.03 |
컴파일 에러는 "컴파일 에러"라고 쓰인 곳을 클릭하면 에러 메시지를 볼 수 있습니다. (0) | 2023.01.02 |