Java의 이상한 정수 상자
방금 이와 유사한 코드를 보았습니다.
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.out.println(a == b);
Integer c = 100, d = 100;
System.out.println(c == d);
}
}
실행 시 이 코드 블록이 인쇄됩니다.
false
true
첫 가 ★★★★★★★★★★★★★★★★★★★★★★★★★★.false
오브젝트이기 의 오브젝트는 2개의 오브젝트로 구성되어 있습니다.==
을 사용하다 왜 두알 가 없어요.true
Integer 값이 특정 범위에 있을 때 실행되는 이상한 자동 상자 규칙이 있습니까?게게무 슨슨?
true
회선은 실제로 언어 사양에 의해 보증됩니다.섹션 5.1.7부터:
박스화 되는 값 p가 true, false, 바이트, \u0000 ~\u007f 의 char, 또는 -128 ~127 의 int 또는 쇼트 번호의 경우, r1 및 r2 는 p 의 2 개의 박스화 변환의 결과라고 합니다.r1 == r2인 경우는 항상 있습니다.
두 번째 출력 라인은 보장되지만 첫 번째 출력 라인은 보장되지 않습니다(아래 인용된 마지막 단락 참조).
이상적으로는 특정 원시 값 p를 상자화하면 항상 동일한 참조가 생성됩니다.실제로는 기존 구현 기법으로는 가능하지 않을 수 있습니다.위의 규칙은 실용적인 절충안이다.위의 마지막 절에서는 특정 공통값을 항상 구분할 수 없는 객체로 분류해야 합니다.구현은 이를 게으르거나 열심히 캐싱할 수 있습니다.
다른 값의 경우, 이 공식은 프로그래머 측의 박스형 값의 아이덴티티에 대한 가정을 허용하지 않습니다.이를 통해 이러한 참조의 일부 또는 전부를 공유할 수 있습니다(필요하지는 않습니다).
이것에 의해, 대부분의 경우, 특히 소형 디바이스의 퍼포먼스 저하가 불필요하게 발생하지 않고, 동작이 바람직한 동작임을 확인할 수 있습니다.예를 들어 메모리 제한이 적은 구현에서는 -32K ~ +32K 범위의 정수 및 길이뿐만 아니라 모든 문자 및 짧은 문자도 캐시할 수 있습니다.
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000; //1
System.out.println(a == b);
Integer c = 100, d = 100; //2
System.out.println(c == d);
}
}
출력:
false
true
예, 'a'와 'b'의 비교를 위해 첫 번째 출력이 생성됩니다. 이 두 가지 다른 참조입니다.포인트 1에서는, 실제로는 다음의 2개의 참조가 작성됩니다.
Integer a = new Integer(1000);
Integer b = new Integer(1000);
은 " " "가 되었습니다.JVM
절약을 노력합니다.Integer
입니다.2번 'd'는 정수입니다.Integer 유형 참조 변수 'd'에 대한 새 개체를 만드는 대신 'c'에서 참조하는 이전에 만든 개체만 할당했습니다.은 <고객명>님에 의해 .JVM
이러한 메모리 절약 규칙은 Integer에만 적용되는 것이 아닙니다.메모리 절약을 위해 다음과 같은 래퍼 개체의 두 인스턴스는 항상 ==이며, 기본 값은 동일합니다.
- 부울
- 바이트
- \u0000 ~의 문자
\u007f
이다) (7f는 10진수 127이다) - -128 ~ 127의 짧은 정수
일정 범위의 정수 객체(아마 -128~127)는 캐시되어 재사용됩니다.이 범위를 벗어나는 정수는 매번 새 개체를 가져옵니다.
Integer Cache는 기본적으로 다음과 같은 목적으로 Java 버전5에서 도입된 기능입니다.
- 메모리 공간 절약
- 퍼포먼스의 향상.
Integer number1 = 127;
Integer number2 = 127;
System.out.println("number1 == number2" + (number1 == number2);
출력: True
Integer number1 = 128;
Integer number2 = 128;
System.out.println("number1 == number2" + (number1 == number2);
출력: False
어떻게?
실제로 Integer 객체에 값을 할당하면 후드 뒤에서 자동 프로모션이 수행됩니다.
Integer object = 100;
실제로는 Integer.valueOf() 함수를 호출하고 있습니다.
Integer object = Integer.valueOf(100);
★★★★★★★★★★★★★★★★의 상세valueOf(int)
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
설명:
이 메서드는 항상 -128 ~127 범위의 값을 캐시하며 이 범위를 벗어나는 다른 값을 캐시할 수 있습니다.
-128 ~ 127 범위의 값이 필요한 경우 매번 일정한 메모리 위치를 반환합니다.단, 127보다 큰 값이 필요한 경우
return new Integer(i);
개체를 시작할 때마다 새 참조를 반환합니다.
나, further further further further further further further,==
Java 연산자는 값이 아닌 두 개의 메모리 참조를 비교하기 위해 사용됩니다.
Object1
1000달러 6달러
Object2
1020년 6월
Object1 == Object2
False
메모리 위치는 다르지만 값이 같기 때문입니다.
네, 값이 특정 범위에 있을 때 적용되는 이상한 자동 상자 규칙이 있습니다.개체 변수에 상수를 할당할 때 언어 정의에서 새 개체를 생성해야 한다는 내용은 없습니다.캐시에서 기존 개체를 재사용할 수 있습니다.
실제로 JVM은 보통 이 목적을 위해 부울 등의 값뿐만 아니라 작은 정수 캐시도 저장합니다.TRUE 및 Boolean.거짓의.
내 생각에 Java는 이미 '상자'로 되어 있는 작은 정수의 캐시를 보관하고 있는 것 같다.왜냐하면 이러한 정수는 매우 일반적이고 기존 객체를 다시 사용하는 것이 새로운 객체를 만드는 것보다 훨씬 많은 시간을 절약할 수 있기 때문이다.
그것은 흥미로운 점이다.이 책에서는 Effective Java는 항상 자신의 클래스에 대해 동등함을 재정의할 것을 제안합니다.또한 Java 클래스의 두 객체인스턴스의 동일성을 체크하려면 항상 동일한 방법을 사용합니다.
public class Scratch
{
public static void main(String[] args)
{
Integer a = 1000, b = 1000;
System.out.println(a.equals(b));
Integer c = 100, d = 100;
System.out.println(c.equals(d));
}
}
반환:
true
true
Integer 참조에 int 리터럴을 직접 할당하는 것은 자동 박스의 한 예입니다.여기서 오브젝트 변환 코드에 대한 리터럴 값은 컴파일러에 의해 처리됩니다.
컴파일 가 변환됩니다.Integer a = 1000, b = 1000;
로로 합니다.Integer a = Integer.valueOf(1000), b = Integer.valueOf(1000);
.
렇렇 so so so soInteger.valueOf()
method는 실제로 정수 객체를 제공합니다.메서드의 소스 코드를 보면 메서드가 -128 ~127(표준) 범위의 정수 객체를 캐시하는 것을 명확하게 알 수 있습니다.
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
새로운 오브젝트를 하여 반환하는 " " " 를 사용합니다.Integer.valueOf()
Integer에서 합니다.IntegerCache
127번으로 하겠습니다. -128을 사용하다
Java는 이러한 정수 개체를 캐시합니다. 왜냐하면 이 범위의 정수는 일상 프로그래밍에서 많이 사용되기 때문에 간접적으로 메모리를 절약할 수 있습니다.
캐시는 스태틱블록 때문에 클래스가 메모리에 로드되면 처음 사용할 때 초기화됩니다.는 캐시의 최대 범위를 할 수 .-XX:AutoBoxCacheMax
JVM 션 j
정수이다.에는 Integer Cache도 .ByteCache, ShortCache, LongCache, CharacterCache
★★★★★★에Byte, Short, Long, Character
각각 다음과 같다.
자세한 내용은 제 기사 Java Integer Cache - Why Integer.valueOf(127) == Integer.valueOf(127) Is True를 참조하십시오.
Java에서 박스는 -128에서 127 사이의 정수 범위에서 작동합니다.이 범위의 숫자를 사용하는 경우 == 연산자와 비교할 수 있습니다.범위를 벗어나는 정수 객체의 경우 equals를 사용해야 합니다.
「 」의 하면,Integer
class, 다음과 같이 메서드의 소스를 찾을 수 있습니다.
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
알 수 있어요.Integer
128)(으)의 입니다.Integer.low
( 127 ( )Integer.high
는, 는 자동 박스 처리 중에 참조되는 동일한 객체입니다. 클래스가 있는 을 볼 수 있습니다.IntegerCache
Integer
어레이: "private static inner" 및 "private static inner"의 내부 입니다.Integer
를 누릅니다
이 이상한 상황을 이해하는 데 도움이 될 수 있는 또 다른 흥미로운 예가 있습니다.
public static void main(String[] args) throws ReflectiveOperationException {
Class cache = Integer.class.getDeclaredClasses()[0];
Field myCache = cache.getDeclaredField("cache");
myCache.setAccessible(true);
Integer[] newCache = (Integer[]) myCache.get(cache);
newCache[132] = newCache[133];
Integer a = 2;
Integer b = a + a;
System.out.printf("%d + %d = %d", a, a, b); // The output is: 2 + 2 = 5
}
Java 5에서는 메모리를 절약하고 Integer 타입 오브젝트 핸들링의 성능을 향상시키는 새로운 기능이 도입되었습니다.정수 개체는 내부적으로 캐시되고 동일한 참조 개체를 통해 재사용됩니다.
이는 –127 ~ +127 범위의 정수 값(최대 정수 값)에 적용됩니다.
이 정수 캐시는 자동 상자에 대해서만 작동합니다.정수 개체는 생성자를 사용하여 빌드될 때 캐시되지 않습니다.
상세한 것에 대하여는, 아래의 링크를 참조해 주세요.
★★Integer
에는 JLS 5.1.7. Boxing Conversion에서 요구되는 -128 ~127 범위의 값의 캐시가 포함되어 있습니다.이 때문에,==
을 Integer
값을 얻을 수 있습니다.또, 2개의 「S」를 하면, 2개의 「S」가 됩니다.Integer
이 범위를 벗어나면 2개의 다른 값을 얻을 수 있습니다.
JVM 매개 변수를 변경하여 캐시 상한을 늘릴 수 있습니다.
-XX:AutoBoxCacheMax=<cache_max_value>
또는
-Djava.lang.Integer.IntegerCache.high=<cache_max_value>
내부 클래스 참조:
/**
* Cache to support the object identity semantics of autoboxing for values
* between -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
언급URL : https://stackoverflow.com/questions/3130311/weird-integer-boxing-in-java
'IT' 카테고리의 다른 글
Rails Console은 ID 배열별로 사용자 검색 (0) | 2022.10.18 |
---|---|
php-fpm과 Nginx Docker 컨테이너를 올바르게 링크하려면 어떻게 해야 합니까? (0) | 2022.10.18 |
Spring Data의 MongoTemplate와 MongoRepository의 차이점은 무엇입니까? (0) | 2022.10.18 |
문자열의 제로 패드 숫자 (0) | 2022.10.18 |
서브쿼리 vs 조인 (0) | 2022.10.18 |