이것은 아마도 많이 이야기 되는 흥미로운 내용일 것입니다.
다음의 코드를 실행하면
Integer a=1000, b=1000;
System.out.println(a == b);
Integer c=100, d=100;
System.out.println(c == d);
다음의 결과를 확인할 수 있습니다.
false
true
이해를 위한 기본: 두 개의 참조 값이 같은 객체를 가리키는 경우, 그것이 == 로 같은 것으로 알고 있습니다. 만약 두 개의 객체가 가르치는 참조가 다를 경우, 같은 내용을 가지고 있어도 == 로 같지 않다는 결과를 받습니다.
그래서 마지막 결괏값 역시 false
여야 합니다.
이 흥미로운 것은 사실이다. 만약 당신이 Integer.java 클래스를 본다면 IntegerCache.java 내부 private 클래스를 확인할 수 있을 것이며, 이 클래스에서 -128부터 127까지의 값을 캐시에 저장한다.
그래서 다음과 같이 우리가 뭔가를 선언 할 때 작은 숫자 값은 캐시에 저장된다.
Integer c = 100;
다음 실행하면 내부에서 어떤 일이 일어나는가?
Integer i = Integer.valueOf(100);
valueOf() 메소드를 확인하면
public static Integer valueOf(int i){
if(i >=-128 && i <= 127){
return IntegerCache.cache[i+(128)];
}
return new Integer(i);
}
만약 값이 범위가 -128에서 127이라면 캐시에 저장된 객체가 전달 될 것이다.
그래서
System.out.println(c == d);
에 결과로 우리는 true를 확인하였다.
당신은 “왜 캐시가 필수일까?” 라는 의문을 가질 것이다.
아마도, 논리적인 근거는 작은 값의 숫자 범위 값은 큰 숫자 하나 보다 더 많이 사용된다. 그래서 같은 객체를 이용하여 메모리 사용량을 줄이는 것이다.
그러나 reflections API를 이용하여 이 기능을 악용할 수 있습니다.
다음 코드를 실행하면, 재미있는 결과를 확인할 수 있습니다.
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Class cache = Integer.class.getDeclaredClasses()[0];
Field myCache = cache.getDeclaredField("cache");
myCache.setAccessible(true);
Integer[] newCache = (Integer[]) myCache.get(cache);
newCache[132] = newCache[133];
int a = 2;
int b = a + a;
System.out.printf("%d + %d = %d", a, a, b);
}
결괏값
2 + 2 = 5
추가 내용 :
warpper class(Integer, Double, Long 등)의 인스턴스의 경우 값에 대한 비교는 equals() 메소드를 이용해야 합니다.
MARK DOWN FILE :
1000_100_Integer.md