머리말
이 기사는 주로 Java의 정수에 대한 관련 내용을 소개하고 참조 및 학습을 위해 공유합니다. 아래에서 많이 말하지 않겠습니다. 자세한 소개를 함께 살펴 보겠습니다.
실제 기생충
며칠 전, 나는 "Java 함수의 매개 변수 전송 메커니즘 - 당신은 그것을 정말로 이해합니까?
일부 트리거는 이전에 Java의 정수에서 연구 되었으므로이 기사를 썼습니다.
교환
먼저 예를 살펴 보겠습니다.
Java를 사용하여 두 개의 정수 유형의 스왑 기능 및 교환 값을 완료하십시오.
public static void test ()는 예외 {Integer a = 1, b = 2; 스왑 (a, b); System.out.println ( "a =" + a + ", b =" + b);} 정적 무효 스왑 (정수 A, 정수 b) {// 구현 해야하는 부품} 먼저
Java 객체가 메모리에 할당되는 방법과 메소드가 매개 변수를 전달하는 방법을 이해하지 못하는 경우 다음 코드를 작성할 수 있습니다.
공개 정적 void Swapone (Integer A, Integer B)은 예외 {integer atempvalue = a; a = b; b = atempvalue;} 런의 결과는 값 a와 b가 교환되지 않았 음을 보여줍니다.
위의 프로그램이 실행될 때 Java 객체가 메모리에 할당되는 방법을 살펴 보겠습니다.
객체 주소 할당
이것으로부터 우리는 두 메소드의 로컬 변수 테이블이 객체 a 및 b의 실제 데이터 주소에 대한 참조를 가지고 있음을 알 수 있습니다.
위에서 구현 된 스왑 함수는 스왑 함수의 로컬 변수 A 및 로컬 변수 B에 대한 참조 만 교환하며 JVM 힙에서 실제 데이터를 교환하지 않습니다.
따라서 주 함수에서 A와 B에 의해 참조 된 데이터는 교환되지 않으므로 기본 함수의 로컬 변수의 A와 B는 변경되지 않습니다.
그렇다면 기본 기능에서 데이터를 교환 할 때 어떻게 작동합니까?
두 번째
위의 관행에 따르면 JVM 힙에서 A와 B의 데이터 값을 교환하는 것을 고려할 수 있습니까?
정수 객체에 대해 간단히 배우겠습니다. 객체의 값을 나타내는 객체 수준의 int 값만 있습니다.
따라서 반사를 사용하여 값을 수정하고 코드는 다음과 같습니다.
public static void swaptwo (Integer A1, Integer B1)는 예외 {field valuefield = integer.class.getDeclaredfield ( "value"); Valuefield.setAccessible (true); int tempavalue = valuefield.getint (a1); valuefield.setint (a1, b1.intvalue ()); Valuefield.setint (B1, Tempavalue);}운영 결과는 기대치와 일치합니다.
놀라다
위의 프로그램이 실행되면 Integer c = 1, d = 2;
샘플 프로그램은 다음과 같습니다.
public static void swaptwo (Integer A1, Integer B1)는 예외 {field valuefield = integer.class.getDeclaredfield ( "value"); Valuefield.setAccessible (true); int tempavalue = valuefield.getint (a1); valuefield.setint (a1, b1.intvalue ()); Valuefield.setInt (b1, tempavalue);} public static void testree ()는 예외 {Integer a = 1, b = 2; swaptwo (a, b); System.out.println ( "a =" + a + "; b =" + b); 정수 c = 1, d = 2; System.out.println ( "c =" + c + "; d =" + d);}출력 결과는 다음과 같습니다.
a = 2; b = 1c = 2; d = 1
놀람하지 말라! 사고 여부! 자극적이든 아니든!
심도있는
정확히 무슨 일이 있었나요? 소환 된 코드를 살펴 보겠습니다.
저자는 IDE 도구를 사용 하여이 .class 파일을 직접 소집합니다.
public static void testthree ()는 예외를 던지려면 {integer a = integer.valueof (1); 정수 b = integer.valueof (2); swaptwo (a, b); System.out.println ( "a =" + a + "; b =" + b); 정수 c = integer.valueof (1); 정수 d = integer.valueof (2); System.out.println ( "c =" + c + "; d =" + d);} Java의 과정에서 원래 유형 int를 정수 유형으로 자동으로 박싱하는 과정에서 Integer.valueOf(int) 메소드가 사용됩니다.
이 방법은 내부적으로 일부 작업을 캡슐화해야하므로 Integer.value 수정 한 후 글로벌 영향을 미칩니다.
이 모든 것은 코드 의이 부분의 코드가 한 번에 붙어 있습니다 (PS : 드래그하지 않는 저자는 좋은 코더입니다).
공개 클래스 정수 { / ** * @since 1.5 * / public static integer valueof (int i) {if (i> = integercache.low && i <= integercache.high) return integercache.cache [i + (-integercache.low)]; 새로운 정수 (I)를 반환합니다. } private static class integercache {정적 최종 int low = -128; 정적 최종 INT High; 정적 최종 정수 캐시 []; static {// 높은 값은 int h = 127 특성으로 구성 될 수 있습니다. 문자열 integercachehighpropvalue = sun.misc.vm.getSavedProperty ( "java.lang.integer.integercache.high"); if (integercachehighpropvalue! = null) {try {int i = parseint (integercachehhighpropvalue); i = math.max (i, 127); // 최대 배열 크기는 정수입니다 .max_value h = math.min (i, integer.max_value- (-low) -1); } catch (numberformatexception nfe) {// 속성을 int로 구문 분석 할 수없는 경우 무시하십시오. }} High = H; 캐시 = 새 정수 [(High -Low) + 1]; int j = 낮음; for (int k = 0; k <cache.length; k ++) 캐시 [k] = 새 정수 (j ++); // 범위 [-128, 127]은 인턴을 받아야합니다 (JLS7 5.1.7) assert integercache.high> = 127; } private integercache () {}} 위에서 볼 수 있듯이 Integer는 내부에 개인 정적 클래스 integercache를 가지고 있으며, 이는 Integer.IntegerCache.low 포함하는 정수 배열을 java.lang.Integer.IntegerCache.high 로 포함하는 정수 배열을 정적으로 초기화합니다.
java.lang.Integer.IntegerCache.high 의 값 범위는 [127~Integer.MAX_VALUE - (-low) -1] 사이입니다.
이 간격에서 Integer.valueOf(int) 함수에 의해 반환 된 모든 객체는 int 값에 따라 계산되며 배열 정수에서 얻어집니다 Integer.IntegerCache.cache . 객체는 동일하고 새 객체가 생성되지 않습니다.
따라서 Integer.valueOf(1) 의 값을 수정하면 Integer.IntegerCache.cache[ 1 - IntegerCache.low ] 의 모든 반환 값이 변경됩니다.
나는 당신의 IQ를 이해해야한다고 생각합니다. 이해하지 못하면 의견 섹션에서 10086으로 전화하십시오.
좋아, [IntegerCache.low~IntegerCache.high) 에없는 부분은 어떻습니까?
분명히, 그들은 운이 좋으며, Integercache에 의해 캐시되지 않고, 그들이 도착할 때마다, 그들은 JVM에 지구 조각 (내륙) (분포)을 할당합니다.
환상
변환 된 매개 변수를 int로 유형으로 변경하면 어떻게됩니까?
public static void testone ()은 예외 {int a = 1, b = 2; 스왑 폰 (a, b); System.out.println ( "a =" + a + ", b =" + b);} 정적 무효 스왑 (int a, int b) {// 구현 해야하는 부품} 저자의 현재 기술을 사용하면 해결책이 없습니다. 전문가들은 공식 계정에 메시지를 남길 수 있습니다. 대단히 감사합니다!
지금까지 스왑 부분이 완료되었습니다.
1 + 1
먼저 코드를 살펴 보겠습니다.
public static void testone () {int one = 1; int 2 = one + one; System.out.printf ( "2 =%d", 2);} 출력은 무엇입니까?
당신이 2라고 말하면, 당신은 그것을 헛된 배운 것입니다. 95169로 직접 전화하십시오.
[Integer.MIN_VALUE~Integer.MAX_VALUE] 간격에서 어떤 가치가있을 수 있는지 확인할 수 있습니다.
놀람하지 말라! 사고 여부! 자극적이든 아니든!
로스트 코드를 하나씩 스트로크합시다.
저자는 IDE 도구를 사용 하여이 .class 파일을 직접 소집합니다.
public static void testone () {int one = 1; int 2 = one + one; System.out.printf ( "2 =%d", 2);} 여기의 변수는 teger.valueOf(int) 에서 호출하지 않았습니다. 이것은 내가 상상했던 것과 다릅니다. 나는 이것이 IDE의 냄비라고 생각합니다.
따라서 컴파일 된 바이트 코드를 결정적으로 확인하십시오. 다음은 발췌의 바이트 코드 중 일부입니다.
LDC "2 =%D"iconst_1anewarray java/lang/objectDupiconst_0iload 2invokestatic java/lang/integer.valueof (i) ljava/lang/intger; (ljava/lang/string; [ljava/lang/object;) ljava/io/printstream; pop
그것이 실제로 IDE의 냄비라는 것을 알 수 있습니다. Integer.valueOf(int) 한 번 호출 할뿐만 아니라 객체 배열도 생성됩니다.
완전한 Java 코드는 다음과 같습니다.
public static void testone () {int one = 1; int 2 = one + one; Object [] params = {integer.valueof (2)}; System.out.printf ( "2 =%d", params);} 따라서 메소드가 호출되기 전에 Integer.IntegerCache.cache[2+128] 의 값을 수정하므로 클래스의 정적 초기화 부분에 일부 코드를 추가하십시오.
공개 클래스 OnePlusOne {static {try {class <?> cacheclazz = class.forname ( "java.lang.integer $ integercache"); Field Cachefield = CacheClazz.getDeclaredfield ( "캐시"); Cachefield.setAccessible (true); Integer [] cache = (Integer []) cachefield.get (null); // 여기서 1 + 1 = 3 캐시로 변경 [2 + 128] = 새 정수 (3); } catch (예외 e) {e.printstacktrace (); }} public static void testone () {int one = 1; int 2 = one + one; System.out.printf ( "2 =%d", 2); }}두 == 2?
Integer.IntegerCache.cache[2 + 128] 의 값을 수정 한 후 변수 2는 2와 같습니까?
public static void testtwo () {int one = 1; int 2 = one + one; System.out.println (2 == 2); System.out.println (Integer.Valueof (2) == 2);}위의 코드 출력은 다음과 같습니다
Truefalse
2 == 2는 정수 권투의 변환 또는 원래 유형의 비교를 포함하지 않기 때문에 원래 유형의 2는 항상 2와 같습니다.
Integer.valueOf(two)==2 의 실제 형태는 Integer.valueOf(two).intValue == 2 , 즉 3 == 2이므로 거짓입니다.
여기서 우리는 당신이 이중 동일 부호를 가진 int 변수의 정수 변수와 null 값을 비교하면 nullpointexception이 던져 질 것임을 알 수 있습니다.
여기의 메소드가 System.out.println("Two=" + two) 으로 대체되면 어떤 종류의 출력이 있습니까? 당신은 그것을 시도 할 수 있습니다.
추신
xcache
| 수업 | 캐시가 있습니까? | 최소 값 | 최대 값 |
|---|---|---|---|
| 부울 | 없음 | - | - |
| 바이트 | 바이 테카시 | -128 | 127 (고정) |
| 짧은 | 바로 가스 | -128 | 127 (고정) |
| 성격 | 캐릭터 캐시 | 0 | 127 (고정) |
| 정수 | IntegerCache | -128 | java.lang.integer.integercache.high |
| 긴 | Longcache | -128 | 127 (고정) |
| 뜨다 | 없음 | - | - |
| 이중 | 없음 | - | - |
java.lang.integer.integercache.high
IntegerCache 클래스 sun.misc.VM.getSavedProperty 높은 수준을 얻는 방법을 읽은 후에는 다음과 같은 질문이있을 수 있습니다. 우리는 하나의 질문-일대일 대답 방법을 지연시키고 사용하지 않을 것입니다.
1.이 값을 JVM에 전달하는 방법은 무엇입니까?
시스템 속성과 마찬가지로 JVM이 시작되면 -Djava.lang.Integer.IntegerCache.high=xxx 설정하여 전달됩니다.
2.이 방법과 System.getProperty 의 차이점은 무엇입니까?
JVM 시스템에 필요한 매개 변수를 사용자가 사용하는 매개 변수와 구별하려면
java.lang.System.initializeSystemClass 가 시작되면 시작 매개 변수는 두 곳에서 저장됩니다.
2.1 모든 JVM이 수신 한 시스템 매개 변수는 Sun.misc.vm.SavedProps에 저장됩니다.
JVM이 시작되면 java.lang.System.initializeSystemClass 메서드를 호출하여 속성을 초기화합니다.
동시에 sun.misc.VM.saveAndRemoveProperties 메서드는 java.lang.System.props 에서 다음 속성을 삭제하도록 호출됩니다.
위에 나열된 속성은 JVM 스타트 업을 위해 설정 해야하는 모든 시스템 매개 변수이므로 보안 고려 사항 및 격리 고려 사항을 위해 사용자가 액세스 가능한 시스템과 분리하십시오.
2.2 java.lang.system.props에서 JVM 시작에 필요한 다음 매개 변수를 제외한 다른 매개 변수를 저장하십시오.
추신 : JDK 1.8.0_91 저자가 사용합니다
Java 9의 IntegerCache
위의 장난 꾸러기 게임 플레이가 타사 의존성 패키지에 나타나면, 미치게 될 프로그래머 그룹이 분명히있을 것이라고 상상해보십시오 (그런 나쁜 게임 플레이를 시도하지 말고 결과는 매우 심각합니다).
다행히도 Java 9는 이것을 제한했습니다. 해당 모듈에 Module-Info.java 파일을 작성할 수 있습니다. 해당 모듈에 액세스 멤버 등의 반사 사용을 제한 할 수 있습니다. 필요에 따라 코드는 필드, 메소드 및 기타 정보 만 액세스 할 수 있습니다. 클래스가 동일한 모듈에 있거나 모듈이 반사 액세스를위한 패키지를 열었을 때만. 자세한 내용은 기사를 참조하십시오.
Java 9에서 IntegerCache를 수정 하시겠습니까?
Lydia와 Asuka에게 귀중한 조언과 교정에 대한 노력에 감사드립니다.
마지막으로 Java의 정수 가치에주의를 기울이지 않는 문제를 여러분과 공유하고 싶습니다.
먼저 코드 스 니펫을 살펴 보겠습니다.
public static void main (String [] args) {Integer a1 = integer.valueof (60); // Danielinbiti 정수 B1 = 60; System.out.println ( "1 : ="+(a1 == b1)); 정수 A2 = 60; 정수 B2 = 60; System.out.println ( "2 : ="+(a2 == b2)); 정수 A3 = 새로운 정수 (60); 정수 B3 = 60; System.out.println ( "3 : ="+(a3 == B3)); 정수 A3 = 새로운 정수 (60); 정수 B3 = 60; System.out.println ( "3 : ="+(a3 == B3)); 정수 A4 = 129; 정수 B4 = 129; System.out.println ( "4 : ="+(a4 == b4)); } 이 코드의 비교 결과가 실행되지 않으면 답이 무엇인지 모르겠습니다.
이 답변을 알기 위해 Java 버퍼 및 힙 문제가 포함됩니다.
Java에서 정수 유형은 -128-127 사이의 숫자에 대한 버퍼이므로 동일한 부호와 일치합니다. 그러나이 범위에 있지 않은 숫자의 경우 힙에 새롭습니다. 따라서 주소 공간이 다르므로 같지 않습니다.
Integer b3=60 , 이것은 포장 과정, 즉 Integer b3=Integer.valueOf(60)
따라서 향후 정수를 만나면 값이 동일한지 여부를 비교하기 위해 intValue() 사용해야합니다.
이중에는 버퍼가 없습니다.
답변
1 : = 참
2 : = 참
3 : = 거짓
4 : = 거짓
요약
위는이 기사의 전체 내용입니다. 이 기사의 내용에 모든 사람의 연구 나 작업에 대한 특정 참조 가치가 있기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다. Wulin.com을 지원 해주셔서 감사합니다.