티스토리 뷰
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를 사용하는 것을 볼 수 있다.
Integer.valueOf(int i)를 보게되면
특정 값 범위에는 캐시를, 그외에는 Integer 객체를 생성하는 것을 볼 수 있다.
그렇다면 캐시의 범위는 어디까지일까??
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를 활용하라고 주의를 준다.)
'JAVA공부 > JAVA' 카테고리의 다른 글
MANIFEST.MF (1) | 2024.02.05 |
---|---|
Apache Kafka - 부분 내용 정리 ③ (0) | 2024.01.22 |
Apache Kafka - 부분 내용 정리 ② (1) | 2024.01.15 |
Java 8 ~ 17 주요 변경점 정리하기 (0) | 2023.09.17 |
Java 성능 모니터링 ②-① 본론 (VisualVM 분석 및 연동) (0) | 2023.09.13 |