티스토리 뷰

JAVA공부/JAVA

Integer 동일 비교

CodingDreamTree 2024. 10. 7. 04:04

Integer 128 != Integer 128 ??

앞서 String Pool에서 문자열의 동일비교에 대해 공부해보았는데,

이번엔 흥미로운 숫자에 대해서도 동일비교가 문제가 되는 상황이 있다.

 

Integer a1 = 1;
Integer a2 = 1;

Integer a3 = 128;
Integer a4 = 128;

Integer a5 = 256;
Integer a6 = 256;

System.out.println(a1 == a2); //true
System.out.println(a3 == a4); //false
System.out.println(a5 == a6); //false

 

왜 이러한 상황이 나오는 것일까?

 

아시다시피 Integer Class는 Object객체이다. 기본형타입과는 다른 비교가 필요하다.

그렇다면 a1,a2를 비교했을때도 false가 나왔어야하는데 무슨 이유로 동일할까??

 

정답은 AutoBoxing속에

Java파일을 컴파일 이후 Byte Code를 보면 AutoBoxing을 할시에 Integer.valueOf를 사용하는 것을 볼 수 있다.

AutoBoxing의 바이트 코드

 

Integer.valueOf(int i)를 보게되면

특정 값 범위에는 캐시를, 그외에는 Integer 객체를 생성하는 것을 볼 수 있다.

valueOf 메서드

 

그렇다면 캐시의 범위는 어디까지일까??

private static final class IntegerCache {
    static final int low = -128;
    static final int high;

    @Stable
    static final Integer[] cache;
    static Integer[] archivedCache;

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                h = Math.max(parseInt(integerCacheHighPropValue), 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        // Load IntegerCache.archivedCache from archive, if possible
        CDS.initializeFromArchive(IntegerCache.class);
        int size = (high - low) + 1;

        // Use the archived cache if it exists and is large enough
        if (archivedCache == null || size > archivedCache.length) {
            Integer[] c = new Integer[size];
            int j = low;
            for(int i = 0; i < c.length; i++) {
                c[i] = new Integer(j++);
            }
            archivedCache = c;
        }
        cache = archivedCache;
        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

 

해당 정적 변수의 값을 보면 최저는 -128이고 최고값은 VM에 저장된 속성값 java.lang.Integer.IntegerCache.high

를 따르는 것을 볼 수 있으며, 딱히 설정이 없는 경우 127까지로 정해져있는 것을 확인할 수 있다.

 

왜 이렇게 하였을까??

주석에 따르면 자주 사용되는 숫자값 -128 ~ 127을 저장해두어 훨씬 더 나은 공간, 시간 성능을 제공하기 위해서라고

쓰여있으며, 원하기에따라 더 넓은 범위값을 캐싱할 수 있다고한다. 

(모든 숫자 래퍼 타입이 캐싱을 적용하는 것이 아니니 주의하자.)

 

결론

래퍼타입을 비교할때는 equals를 활용하자. (Intellij 에서도 Number Object 타입의 비교는 equals를 활용하라고 주의를 준다.)

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함