java.lang.Integer 소스 읽기 (1)
JDK 소스 요약 정보
클래스 선언
public final class Integer extends Number implements Comparable {}
public abstract class Number implements java.io.Serializable {}
compareTo
Comparable가 구현되었습니다. 대응 방법을 살펴보십시오.
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
/**
* jdk1.7 static ,
*/
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
toString(int)
굉장히 많이 쓰는 Tostring 방법을 보겠습니다.
public static String toString(int i) {
// Integer , "-2147483648"
if (i == Integer.MIN_VALUE)
return "-2147483648";
// i , ,size 1, (-)
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
//
char[] buf = new char[size];
//
getChars(i, size, buf);
return new String(buf, true);
}
먼저stringSize 방법을 보십시오. 이 방법은 형삼 i의 위치를 되돌려줍니다.
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE };
// x
static int stringSize(int x) {
// sizeTable , i x (i+1)
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
다시 getChars 방법을 보면 이 방법은 i를 형성하는 모든 숫자를 buf 수조에 채우는 것이다.getChars라는 방법을 보기 전에 형삼 i의 각 위치의 숫자를 어떻게 얻을 수 있는지 생각해 볼 수 있다.사실은 순환이다. ① 매번 10으로 나눈 나머지 (%)는 개위의 숫자를 얻는다.② 그 다음에 형삼 i를 10으로 나누면 정수로 나누면 끝수(즉 앞의 여수)는 버려진다.③ ①②형삼 i가 0이 될 때까지 반복한다.예를 들어 12, 첫 번째 순환: 10을 제외하고 2를 얻으면 한 자릿수의 숫자가 2이다. 그리고 10을 나누면 1을 얻고 한 자릿수의 2는 버려진다. 두 번째 순환: 10을 제외하고 1을 얻고 10을 나누면 0을 얻는다. 그래서 각각 2와 1을 얻고 순환이 끝난다.코드로 보면 다음과 같습니다.
while (true) {
r = i % 10;
i /= 10;
// ↓
// n , r buf n
if (i == 0) break;
이상은 양수의 상황만 고려했고 음수의 경우 재순환이 끝난 후 buf의 0번째 위치에'-'를 추가하면 된다. 전체 코드는 다음과 같다.
static void myGetChars(int i, int index, char[] buf) {
int charPos = index;// buf
char sign = 0;//
if (i < 0) {
sign = '-';
i = -i;//
}
while (true) {
int r = i % 10;
i /= 10;
buf [--charPos] = digits [r];// r 'r', buf
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;
}
}
보아하니 getChars의 기능을 실현한 것 같은데, jdk에서는 이렇게 하지 않나요?정답: no!원본 보기:
static void getChars(int i, int index, char[] buf) {
int q, r;// r , buf
int charPos = index;// buf
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// i >= 65536
// buf 2 , i ,
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
// r = i - (q * 100)
// q << 6 = 2^6 = 64
// q << 5 = 2^5 = 32
// q << 2 = 2^2 = 4
// i - q * 100 r i 2 , i%100, , ,
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;
// r
buf [--charPos] = DigitOnes[r];
// r
buf [--charPos] = DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) {
// i/10,
q = (i * 52429) >>> (16+3);
r = i - ((q << 3) + (q << 1)); // r = i-(q*10)
buf [--charPos] = digits [r];// r 'r', buf
i = q;
if (i == 0) break;
}
if (sign != 0) {// , '-'
buf [--charPos] = sign;
}
}
이곳에는 몇 가지 비교적 재미있는 곳이 있다.
q = (i * 52429) >>> (16+3);
에 대해 이 코드는 q = i / 10;
와 같고 ALU가 곱셈과 위치 이동 연산을 집행하는 속도가 제곱법의 연산 속도보다 빠를 것이다.그러나 왜 52429과 2^19(2의 19차원, 무기호 오른쪽으로 19자리를 옮기는 것은 2를 제외한 19차원)에 해당하는지 정밀도가 동시에 넘치지 않도록 고려한 것이다.먼저 정밀도에 대해 말하자면 (double) 52429/52488=0.100000381469, 이 정밀도는 i의 10분의 1을 구할 수 있다. 예를 들어 정밀도가 부족한 것을 골라서 0.103을 구한다면 i가 999999*0.103=102이고 999의 10분의 199가 아니다.한편, 65536=2^16524229<65536, 그래서 i*52429<2^32, 넘치지 않고 i*52429는 결과가 마이너스로 변하는 문제를 초래할 수 있다. 이것은 중간 결과일 뿐이다. 부호가 없이 19위를 오른쪽으로 이동한 후에 높은 위치가 모두 0을 보충하면 결과는 q가 정수이다.이상에서 알 수 있듯이 jdk는 여전히 매우 엄격하고 효율을 위해 노력했다.toString(int, int)
다음은 toString (int i, int radix) 을 보십시오. 이 방법은 주로 형삼 i를 radix 진법으로 바꾸는 것입니다.
public static String toString(int i, int radix) {
// 2 36 , 10
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
/* Use the faster version */
// 10 ,
if (radix == 10) {
return toString(i);
}
// Integer 33 , 32 , 1
char buf[] = new char[33];
boolean negative = (i < 0);// , i
int charPos = 32;// buf , 32
// i , ,
if (!negative) {
i = -i;
}
// i%radix buf (charPos)
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
// i , '-'
if (negative) {
buf[--charPos] = '-';
}
// , buf charPos , 33-charPos, , 32
return new String(buf, charPos, (33 - charPos));
}
toString()
인덱스가 봉인된value를 문자열로 바꾸는 것은 어렵지 않습니다.
public String toString() {
return toString(value);
}
toHexString(int)
다음은 몇 개의 무기호 진법의 전환을 보겠습니다.
public static String toHexString(int i) {
return toUnsignedString(i, 4);
}
public static String toOctalString(int i) {
return toUnsignedString(i, 3);
}
public static String toBinaryString(int i) {
return toUnsignedString(i, 1);
}
/**
*
* , , 17 0000 0000 0000 0000 0000 0001 0001 0001,-17 1111 1111 1111 1111 1111 1111 1110 1111
*/
private static String toUnsignedString(int i, int shift) {
// , 32
char[] buf = new char[32];
//
int charPos = 32;
//
int radix = 1 << shift;
// , 0001, 0111, 1111
int mask = radix - 1;
do {
// i & mask, , , , 0001 0001 8 , 3 :00 010 001, 0 2 1, 17 8 21,i & mask , mask , digits
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
i & mask의 과정을 보여 줍니다.
parseInt(String, int)
다음으로parseInt 방법, 진법 변환의 공식을 보겠습니다. a*radix^0+b*radix^1+c*radix^2+...+xx * radix^(n-1)
/**
*
*
*/
public static int parseInt(String s, int radix)
throws NumberFormatException
{
/*
* WARNING: This method may be invoked early during VM initialization
* before IntegerCache is initialized. Care must be taken to not use
* the valueOf method.
*/
// s , [2, 36], jdk , , [2, 36] 10 , ,
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
//
int result = 0;
// , , Integer.MIN_VALUE
boolean negative = false;
int i = 0, len = s.length();
//
int limit = -Integer.MAX_VALUE;
// ,
int multmin;
// Character#digit
int digit;
if (len > 0) {
//
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
// , Integer.MIN_VALUE
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
// , 10 211, multmin = 211 / 10 = 21, result 30, result *= radix 211, 。
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
// , Character
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
// (limit ) , result > multmin
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;// , a * radix^(n-1)
// , ,result 210, digit 2, result = 212, 。
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;// ,
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
//
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
valueOf()
이어서valueOf 방법을 살펴보자.valueOf 방법을 보기 전에 Integer Cache를 먼저 보아야 한다. 말 그대로 이것은 정수의 캐시이다. 기본적으로 Integet Cache는 [-128,127]의 모든 실례를 캐시하기 때문에 정상적인 상황에서 이 두 값 범위 내의 이미지는 모두 같다(=true). 왜냐하면 그들은 같은 메모리의 대상을 인용하기 때문이다.예를 들면, 당연히 시작 매개 변수
-XX:AutoBoxCacheMax=size
를 통해 캐시의 내용을 수정할 수 있다. (size는 127보다 커야 하고, 그렇지 않으면 127로 간주해서 jvm의 캐시를 [-size-1,size]의 대상으로 할 수 있다.코드 보기: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) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);// 127 , 127
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
// , cache
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
구체적으로 value Of 방법을 보십시오
// parseInt
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;// IntegetCache 127
// [IntegetCache.low, Integer.high]
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);//
}
나누기가 쉽지 않으니, 옮겨 싣고 출처를 밝혀 주십시오.
java.lang.Integer 소스 읽기 (1) 주소:https://www.jianshu.com/p/02c1d9092347
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.