방금 다음과 유사한 코드를 보았습니다.
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
합니다. 두 개체가 별도의 개체이기 때문에 ==
참조를 비교합니다. 그러나 두 번째 진술이 반환되는 이유를 알 수 없습니다 true
. Integer의 값이 특정 범위에있을 때 시작되는 이상한 오토 박싱 규칙이 있습니까? 여기서 무슨 일이 일어나고 있습니까?
답변
true
라인은 실제로 언어 사양에 의해 보장된다. 에서 섹션 5.1.7 :
boxing되는 값 p가 true, false, a byte, \ u0000 ~ \ u007f 범위의 char 또는 -128에서 127 사이의 int 또는 짧은 숫자이면 r1과 r2를 두 개의 boxing 변환의 결과로 둡니다. 의 p. 항상 r1 == r2 인 경우입니다.
두 번째 출력 라인은 보장되지만 첫 번째 라인은 보장되지 않는다는 것을 암시합니다 (아래 인용 된 마지막 단락 참조).
이상적으로 주어진 기본 값 p를 박싱하면 항상 동일한 참조가 생성됩니다. 실제로 이것은 기존 구현 기술을 사용하여 실현 가능하지 않을 수 있습니다. 위의 규칙은 실용적인 타협입니다. 위의 마지막 절에서는 특정 공통 값을 항상 구별 할 수없는 개체로 묶어야합니다. 구현은 이들을 느리게 또는 열심히 캐시 할 수 있습니다.
다른 값의 경우,이 공식은 프로그래머 측에서 박스형 값의 식별에 대한 어떠한 가정도 허용하지 않습니다. 이렇게하면 이러한 참조의 일부 또는 전체를 공유 할 수 있습니다 (필수는 아님).
이렇게하면 특히 작은 장치에서 과도한 성능 저하없이 대부분의 일반적인 경우 동작이 원하는 동작이됩니다. 예를 들어 메모리 제한이 적은 구현은 -32K-+ 32K 범위의 정수 및 long뿐만 아니라 모든 문자와 단락을 캐시 할 수 있습니다.
답변
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에서는 실제로 다음과 유사한 두 개의 참조가 생성됩니다.
Integer a = new Integer(1000);
Integer b = new Integer(1000);
두 번째 출력 은가 범위 (-128에서 127)에 속할 JVM
때 메모리를 절약하려고하기 때문에 생성 됩니다 Integer
. 지점 2에서는 ‘d’에 대한 Integer 유형의 새로운 참조가 생성되지 않습니다. Integer 유형 참조 변수 ‘d’에 대한 새 개체를 만드는 대신 ‘c’에서 참조하는 이전에 만든 개체 만 할당합니다. 이 모든 작업은 JVM
.
이러한 메모리 절약 규칙은 정수에만 적용되는 것이 아닙니다. 메모리 절약을 위해 다음 래퍼 개체의 두 인스턴스 (복싱을 통해 생성되는 동안)는 항상 기본 값이 동일한 ==입니다.
- 부울
- 바이트
- 캐릭터로부터 \ u0000의 행
\u007f
(7F는 십진수 127) - -128 에서 127 까지의 Short 및 Integer
답변
일부 범위 (-128에서 127까지)의 정수 개체는 캐시되고 다시 사용됩니다. 이 범위를 벗어난 정수는 매번 새로운 객체를 얻습니다.
답변
예, 값이 특정 범위에있을 때 시작되는 이상한 오토 박싱 규칙이 있습니다. Object 변수에 상수를 할당 할 때 언어 정의에 새 개체를 만들어야한다는 내용이 없습니다. 캐시에서 기존 개체를 재사용 할 수 있습니다.
실제로 JVM은 일반적으로 이러한 목적을 위해 작은 정수 캐시와 Boolean.TRUE 및 Boolean.FALSE와 같은 값을 저장합니다.
답변
내 생각에 Java는 매우 일반적이기 때문에 이미 ‘박스형’인 작은 정수의 캐시를 유지하고 새 개체를 만드는 것보다 기존 개체를 재사용하는 데 많은 시간을 절약합니다.
답변
흥미로운 점입니다. 책에서 Effective Java 는 항상 자신의 클래스에 대해 같음을 재정의 할 것을 제안합니다. 또한 Java 클래스의 두 개체 인스턴스에 대한 동등성을 확인하려면 항상 equals 메소드를 사용하십시오.
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
답변
Java에서 boxing은 Integer에 대해 -128에서 127 사이의 범위에서 작동합니다. 이 범위의 숫자를 사용하는 경우 == 연산자와 비교할 수 있습니다. 범위를 벗어난 Integer 개체의 경우 같음을 사용해야합니다.