이 기사에서 저자는 자동 권투 및 Unboxing 인 Java에서 매우 중요하고 흥미로운 기능을 소개하고 소스 코드에서 자동 권투 및 Unboxing의 원리를 해석 할 것입니다. 동시에,이 기능은 또한 함정을 남깁니다. 개발자가주의를 기울이지 않으면이 함정에 쉽게 떨어질 것입니다.
오토 옥싱
정의
Java 프로그램을 작성할 때 사람들은 종종 정수 객체를 다음과 같은 방식으로 정의합니다.
정수 i = 100;
위의 코드에서, 당신은 내가 Type Integer의 참조이고 100은 Java (원시 데이터 유형)의 기본 데이터 유형이라는 것을 알 수 있습니다. 기본 데이터 유형을 해당 래퍼 클래스에 직접 전달하는이 방법은 자동 권투입니다.
JDK 1.5에서 자동 복싱이 처음으로 도입되었습니다. JDK 1.5 이전에는 값이 100 인 정수 객체를 정의하려면 다음을 수행해야합니다.
정수 i = 새로운 정수 (100);
원칙
위의 코드 "정수 i = 100;"에서 중단 점을 만들어 봅시다. 그리고 그것을 따르십시오.
다음으로, 우리는 프로그램이 정수 클래스의 가치 (INT I) 방법으로 이동한다는 것을 알 수 있습니다.
/** * 지정된 * <tt> int </tt> 값을 나타내는 <tt> integer </tt> 인스턴스를 반환합니다. * 새로운 <tt> 정수 </tt> 인스턴스가 필요하지 않은 경우,이 방법 *은 일반적으로 생성자 * {@link #integer (int)}보다 선호하는 경우 * 자주 요청 된 값을 캐싱하여 상당히 더 나은 공간과 시간 성능을 산출 할 수 있기 때문입니다. * * @param i an <code> int </code> 값. * @return a <tt> integer </tt> 인스턴스 <tt> i </tt>. * @since 1.5 */ public static integer valueof (int i) {if (i> = -128 && i <= integercache.high) return integercache.cache [i + 128]; 그렇지 않으면 새 정수 (i)를 반환합니다. }다시 말해, 포장은 JDK로, integer.valueof (100)에 대한 호출을 완료하는 데 도움이됩니다.
Unboxing
정의
정수 integer100 = 100; int int100 = integer100;
위의 코드에서 Integer100은 Type Integer에 대한 참조이고 int100은 int 유형의 기본 데이터 유형임을 알 수 있습니다. 그러나 정수 유형 객체를 해당 원본 데이터 유형의 변수에 할당 할 수 있습니다. 이것은 Unboxing입니다.
Unboxing은 포장과 반대입니다. 권투는 원시 데이터 유형을 해당 캡슐화 된 클래스에 할당하는 변수입니다. Unboxing이란 캡슐화 된 클래스의 변수를 해당 원래 데이터 유형의 변수에 할당하는 것을 의미합니다. 포장 및 개봉의 이름도 매우 적절합니다.
원칙
나는 모든 사람들이 Unboxing 과정에서 JDK가 우리를 위해 무엇을했는지 추측했다고 생각합니다. 실험을 통해 우리의 추측을 증명합시다.
위 코드의 두 번째 줄에 중단 점을 설정하십시오. 즉, "int int100 = integer100"에서 중단 점을 설정하십시오. 그리고 그것을 따르십시오.
우리는 프로그램이 Integer의 intvalue () 메소드로 이동한다는 것을 알 수 있습니다.
/** *이 <code> 정수 </code>의 값을 * <code> int </code>로 반환합니다. */ public int intvalue () {return value; }즉, JDK는 intvalue () 메소드에 대한 호출을 완료하는 데 도움이됩니다. 위의 실험의 경우 Integer100의 intvalue () 메소드를 호출하고 리턴 값을 Int100에 할당하는 것입니다.
펼친
실험 1
정수 integer400 = 400; int int400 = 400; System.out.println (integer400 == int400);
위 코드의 세 번째 줄에서 Integer400 및 Int400은 == run을 실행합니다. 이 두 가지는 다른 유형의 변수입니다. Integer400 Unboxing 또는 Int400 포장입니까? 작업 결과는 무엇입니까?
== 작동은 두 객체의 주소가 동일한지 또는 두 기본 데이터 유형의 값이 동일한지 여부를 결정하는 것입니다. 따라서 Integer400이 박스되지 않은 경우 두 기본 유형의 값이 비교되고 현재 실행 결과가 사실이어야한다는 것을 의미합니다. int400이 포장 된 경우 두 객체의 주소가 동일하고 현재 실행 결과가 거짓이어야 함을 의미합니다. (저자가 400에 할당하는 이유는 나중에 논의 될 함정과 관련이 있습니다).
우리의 실제 실행 결과는 사실입니다. 그래서 그것은 Integer400 Unboxing이었다. 코드 추적의 결과는 이것을 증명합니다.
실험 2
정수 integer100 = 100; int int100 = 100; System.out.println (integer100.equals (int100));
위 코드의 세 번째 줄에서 integer100 메소드의 매개 변수는 int100입니다. Equals 메소드의 매개 변수는 기본 데이터 유형이 아니라 객체라는 것을 알고 있으므로 여기서는 int100 포장되어야합니다. 코드 추적의 결과는 이것을 증명합니다.
실제로, 메소드의 매개 변수 유형이 원래 데이터 유형이고 전달 된 매개 변수 유형이 캡슐화 클래스 인 경우 자동으로 Unboxed가됩니다. 따라서 메소드의 매개 변수 유형이 캡슐화 유형이고 전달 된 매개 변수 유형이 원래 데이터 유형 인 경우 자동으로 박스가됩니다.
실험 3
정수 integer100 = 100; int int100 = 100; Long Long200 = 200L; System.out.println (integer100 + int100); System.out.println (long200 == (integer100 + int100)); System.out.out.println (long200.equals (integer100 + int100));
첫 번째 실험에서, 우리는 기본 데이터 유형이 캡슐화 클래스에서 == 작동하면 캡슐화 클래스가 발행되지 않는다는 것을 알게되었습니다. +, -, *, /? 우리는이 실험에서 알 수 있습니다.
+ 작동 인 경우 기본 데이터 유형이 박스로 표시됩니다.
• 4 행에서 Integer100+int100은 Type Integer and value 200의 오브젝트 O를 얻고이 객체의 toString () 메소드를 실행하고 "200"을 출력합니다.
• 5 행에서 integer100+int100은 유형 정수의 개체 O와 200의 값을 얻습니다. == 작동은이 객체를 Long200 객체와 비교합니다. 분명히, 거짓은 출력이 될 것입니다.
• 6 행에서 integer100+int100은 유형 정수 및 값 200의 오브젝트 O를 얻습니다. Long 's Equals 메소드는 모두 Long200을 O와 비교합니다. 둘 다 다른 유형의 캡슐화 된 클래스이므로 출력은 False입니다.
+ 작동 인 경우 캡슐화 클래스는 Unboxed가됩니다.
• 4 행에서 Integer100+int100은 유형 int 및 값 200의 기본 데이터 유형 B를 얻은 다음 Box B를 얻으려면 O를 얻고이 객체의 toString () 메소드를 실행하고 "200"을 출력합니다.
• 5 행에서 Integer100+Int100은 유형 int 및 값 200의 기본 데이터 유형 B1을 얻습니다. 분명히 B1 == B2 및 출력이 사실입니다.
• 6 행에서 Integer100+Int100은 유형 int 및 값 200의 기본 데이터 유형 B를 얻을 수 있습니다. Long 's Equals Method Box B이지만, 권투는 O와 Long200이 다른 유형의 객체이기 때문에 유형 정수의 OBENCE ON OBJECT O의 OBENT O의 객체 O를 제공합니다. 따라서 출력은 거짓입니다.
프로그램 실행 결과는 다음과 같습니다.
200
진실
거짓
따라서 두 번째 추측은 정확합니다.
덫
트랩 1
정수 integer100 = null;
int int100 = integer100;
이 두 줄의 코드는 완전히 합법적이며 완전히 컴파일 될 수 있지만 실행되면 널 포인터 예외가 발생합니다. 그 중에서도 Integer100은 유형 정수의 대상이며, 물론 Null을 가리킬 수 있습니다. 그러나 두 번째 줄에서는 integer100이 박스가 풀릴 것입니다. 따라서 Unboxing은 캡슐화 된 클래스 객체가 NULL인지 여부에 특별한주의를 기울여야합니다.
트랩 2
정수 i1 = 100;
정수 i2 = 100;
정수 i3 = 300;
정수 i4 = 300;
System.out.println (i1 == i2);
System.out.println (i3 == i4);
i1, i2, i3 및 i4는 모두 정수 유형이므로 실행 결과는 거짓이어야한다고 생각합니다. 그러나 실제 실행 결과는 "System.out.println (i1 == i2);"입니다. 사실이지만 "System.out.println (i3 == i4);" 거짓입니다. 이것은 두 정수 유형의 참조 인 i1과 i2의 참조가 동일한 물체를 가리키고 i3과 i4는 다른 물체를 가리 킵니다. 왜? 그것들은 모두 정수 (int I) 메소드라고 부르지 않습니까?
Integer.Valueof (int I) 메소드를 다시 살펴 보겠습니다.
/** * 지정된 * <tt> int </tt> 값을 나타내는 <tt> integer </tt> 인스턴스를 반환합니다. * 새로운 <tt> 정수 </tt> 인스턴스가 필요하지 않은 경우,이 방법 *은 일반적으로 생성자 * {@link #integer (int)}보다 선호하는 경우 * 자주 요청 된 값을 캐싱하여 상당히 더 나은 공간과 시간 성능을 산출 할 수 있기 때문입니다. * * @param i an <code> int </code> 값. * @return a <tt> integer </tt> 인스턴스 <tt> i </tt>. * @since 1.5 */ public static integer valueof (int i) {if (i> = -128 && i <= integercache.high) return integercache.cache [i + 128]; 그렇지 않으면 새 정수 (i)를 반환합니다. }우리는 i> = -128이고 i <= integercache.high, integercache.cache [i + 128]가 직접 반환된다는 것을 알 수 있습니다. 그중에서도 IntegerCache는 내부 정적 정수 클래스이며 원래 코드는 다음과 같습니다.
개인 정적 클래스 integercache {정적 최종 INT High; 정적 최종 정수 캐시 []; 정적 {최종 int low = -128; // 높은 값은 속성 int h = 127로 구성 될 수 있습니다. if (integercachehighpropvalue! = null) {// long.decode 여기에서 초기화하려면 int i = long.decode (integercachehighpropvalue) .intvalue (); i = math.max (i, 127); // 최대 배열 크기는 정수입니다 .max_value h = math.min (i, integer.max_value - low); } High = H; 캐시 = 새 정수 [(High -Low) + 1]; int j = 낮음; for (int k = 0; k <cache.length; k ++) 캐시 [k] = 새 정수 (j ++); } private integercache () {}}IntegerCache에는 정적 멤버 변수 캐시가 있으며 이는 256 개의 요소가있는 배열 인 것을 분명히 알 수 있습니다. 캐시는 또한 IntegerCache에서 초기화됩니다. 즉, I-TH 요소는 I-128의 값을 가진 정수 객체입니다. -128 ~ 127은 가장 일반적으로 사용되는 정수 객체 이며이 접근법은 성능을 크게 향상시킵니다. 또한 "integeri1 = 100; 정수 i2 = 100;", i1 및 i2가 동일한 물체를 얻는 것입니다.
확장에서 두 번째 실험을 비교하면 캡슐화 클래스가 실행될 때 == 기본 유형으로 실행되면 캡슐화 클래스가 Unbox가 및 비스듬한 결과가 기본 유형과 비교된다는 것을 알게되었습니다. 두 개의 캡슐화 클래스가 실행되는 경우 == 다른 객체와 함께 실행되는 경우, 두 객체의 주소, 즉 두 참조가 동일한 객체를 가리키는 지 여부를 결정합니다.
위의 기사에서는 Java Automatic Packing 및 Unboxing에 대해 간략하게 설명하며 트랩은 내가 공유하는 모든 콘텐츠입니다. 나는 그것이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.