jdk 1.8 기반 자바 소스 상세 설명 Integer


public final class Integer extends Number implements Comparable<Integer>
Integer 는 final 에 의 해 수식 되 었 기 때문에 이 종 류 는 계승 할 수 없 으 며,동시에 Integer 는 Number 류 를 계승 하 였 기 때문에 Integer 를 int,double,float,long,byte 와 short 형식의 데이터 로 변환 할 수 있 으 며,또한 comparable 인터페이스 도 실현 되 었 기 때문에 Integer 류 도 자 연 스 럽 게 정렬 할 수 있다.
구조 방법 은 두 가지 밖 에 없다.

public Integer(int value) {
this.value = value;
}

public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
우 리 는 주로 두 번 째 구조 방법 을 보고 문자열 을 입력 한 다음 에 parseInt 방법 을 호출 한 다음 에 parseInt 의 소스 코드 에 들 어 갑 니 다.

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.
*/
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;
// //     
boolean negative = false;
int i = 0, len = s.length();
//             ,int      -2 31   2 31    
int limit = -Integer.MAX_VALUE;
//    
int multmin;
//     
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
//       0,    "-","+"     
if (firstChar < '0') { // Possible leading "+" or "-"
//   
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')//   
throw NumberFormatException.forInputString(s);
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
/**
*     ,     result *= radix;          
*          ,       32 int     -2147483648~2147483647
*/
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
//     ,      radix       10    , :
//Character.digit('a',16),    10;
//              ,    -1:
//Character.digit('t',16),   -1,Character.digit('a',10),   -1
digit = Character.digit(s.charAt(i++),radix);
//  -1      
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
//       
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
/**
*              
*/
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}
이 방법 에서 가장 핵심 적 인 절 차 는 1.result*=radix 이다.2、result -= digit; 이 두 단 계 를 거 쳐 문자열 을 수치 형식 으로 변환 합 니 다.대략 절 차 는 이렇다.
  • 문자열'1234'가 int 형식 으로 바 뀌 면 result 의 초기 값 은 0 이 고 radix 는 기본 값 은 10 입 니 다.
  • 먼저 문자열 의 첫 번 째 문자 1 을 캡 처 하고(여 기 는 각종 검 사 를 무시 합 니 다)첫 번 째 계산 result=0*10=0 을 거 칩 니 다.2 부 컴 퓨 팅 result=0-1=-1;
  • 첫 번 째 순환 이 끝 난 후 result 의 값 은-1
  • 로 바 뀌 었 다.
  • 두 번 째 문자 2 를 캡 처 하고 result=-1*10=-10,result=-10-2=-12;
  • 세 번 째 문자 3 을 캡 처 합 니 다.result=-12*10=-120,result=-120-3=-123;
  • 네 번 째 문자 4 를 캡 처 합 니 다.result=-123*10=-1230,result=-1230-4=-1234;
  • 순환 이 끝 났 습 니 다.이때 result 의 값 은-1234 이 고 문자열 이 정수 형 으로 전환 되 었 습 니 다.되 돌아 오 면 됩 니 다.
  • 면접 문제 에서 문 제 를 끄 집어 내 고 소스 코드 를 읽 어 이 문 제 를 해결 하 겠 습 니 다.
    
    public static void main(String[] args) {
    Integer i1 = 100;
    Integer i2 = 100;
    Integer i3 = 200;
    Integer i4 = 200;
    Integer i5 = Integer.valueOf(100);
    Integer i6 = Integer.valueOf(100);
    Integer i7 = new Integer(100);
    System.out.println("i1 == i2     :" + (i1 == i2));
    System.out.println("i3 == i4     :" + (i3 == i4));
    System.out.println("i5 == i6     :" + (i5 == i6));
    System.out.println("i1 == i5     :" + (i1 == i5));
    System.out.println("i1 == i7     :" + (i1 == i7));
    }
    실행 결 과 는:
    
    i1 == i2     :true
    i3 == i4     :false
    i5 == i6     :true
    i1 == i5     :true
    i1 == i7     :false
    우 리 는 먼저 첫 번 째 와 두 번 째 결 과 를 살 펴 보 자.똑 같이 두 개의 같은 수 치 를 비교 하 는데 왜 다른 결과 가 있 을 까?이어서 나 는 소스 코드 를 통 해 원인 을 설명 할 것 이다.
    우선,우 리 는 컴 파일 을 통 해 class 파일 의 바이트 코드 를 가 져 옵 니 다.

    그림 에서 볼 수 있 듯 이 Integer i1=100 명령 을 실행 할 때 컴 파일 러 는 Integer 의 정적 방법 인 value Of 를 호출 합 니 다.다음은 value Of 방법 이 어떻게 실현 되 는 지 살 펴 보 겠 습 니 다.
    
    public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
    }
    이 코드 는 매우 간단 해 보 입 니 다.Integer 에는 정적 내부 클래스 인 Integer Cache 가 있 습 니 다.이 방법 을 호출 할 때 먼저 이 값 이 캐 시 범위 내 에 있 는 지 여 부 를 판단 합 니 다.만약 에 캐 시 에 있 는 수 치 를 직접 되 돌려 주지 않 으 면 새로운 대상 으로 돌아 갑 니 다.여기 서 우 리 는 위의 문제 의 답 을 이미 알 고 있 는 것 같 습 니 다.다음은 정적 내부 류 를 계속 보 세 요.
    
    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
    //      (      )  (-128)~ 127,    java.lang.Integer.IntegerCache.high
    //high            
    int h = 127;
    String integerCacheHighPropValue =
    sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    if (integerCacheHighPropValue != null) {
    try {
    int i = parseInt(integerCacheHighPropValue);
    //       127      
    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;
    //          -128 ~ 127
    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() {}
    }
    내부 클래스 는 클래스 가 실례 화 될 때 만 실례 화 되 고 한 번 만 실례 화 된다 는 것 을 알 고 있 습 니 다.캐 시 작업 은 정적 코드 블록 에서 이 루어 집 니 다.즉,클래스 가 실례 화 될 때 데 이 터 는 이미 캐 시 되 었 고 다음 에 사용 할 때 캐 시 된 데 이 터 를 직접 사용 할 수 있 습 니 다.
    현재 우 리 는 위의 문제 로 돌 아 왔 습 니 다.결과 1 에서 두 데 이 터 는 모두 100 입 니 다.캐 시 범위 에서 i1 과 i2 는 같은 메모리 주 소 를 가리 키 기 때문에 true 로 돌아 갑 니 다.결과 2 중 두 개 수 는 모두 200 으로 캐 시 범 위 를 넘 어 섰 기 때문에 new 에서 두 개의 대상 이 나 왔 기 때문에 그들의 메모리 주소 가 일치 하지 않 고 결 과 를 false 로 되 돌려 주 었 습 니 다.또한,value Of 를 사용 하 는 것 은=연산 자 할당 을 사용 할 때 와 같 기 때문에 결과 3 과 결과 4 는 true 로 되 돌아 갑 니 다.결과 5 에 서 는 new 키 워드 를 직접 사용 하여 대상 을 만 듭 니 다.따라서 메모리 주 소 는 일치 하지 않 을 것 입 니 다.결 과 는 false 입 니 다.
    그렇다면 지금 문제 가 또 생 겼 다.그렇다면 나 는 두 정수 의 크기 를 어떻게 판단 할 것 인가?원본 계속 보기
    
    /**
    * The value of the {@code Integer}.
    *
    * @serial
    */
    private final int value;
    public boolean equals(Object obj) {
    if (obj instanceof Integer) {
    return value == ((Integer)obj).intValue();
    }
    return false;
    }
    public int intValue() {
    return value;
    }
    네,맞아요.두 수치 가 큰 시간 을 비교 할 때 equals 방법 으로 비교 할 수 있 습 니 다.소스 코드 에서 value 의 유형 은 int 형 이 고 intValue 가 돌아 오 는 것 도 value 이기 때문에 두 수의 크기 를 판단 할 수 있 습 니 다.
    
    public static void main(String[] args) {
    Integer i1 = 200;
    Integer i2 = 200;
    System.out.println("i1 == i2     :" + i1.equals(i2)); //true
    }
    보충:equals 와=의 차이 점:
    equals 는 두 수치의 크기 를 비교 합 니 다.==두 가지 경우 가 있 습 니 다.기본 데이터 형식 을 비교 하면=equals 와 마찬가지 로 크기 를 비교 합 니 다.참조 형식 이나 배열 이 라면 메모리 주 소 를 비교 합 니 다.
    getChars 방법:
    
    static void getChars(int i, int index, char[] buf) {
    int q, r;
    int charPos = index;
    char sign = 0;
    
    if (i < 0) {
    sign = '-';
    i = -i;
    }
    
    // Generate two digits per iteration
    //          
    while (i >= 65536) {
    q = i / 100;
    // really: r = i - (q * 100);
    //               ,r     
    r = i - ((q << 6) + (q << 5) + (q << 2));
    i = q;
    //         
    buf [--charPos] = DigitOnes[r];
    //  
    buf [--charPos] = DigitTens[r];
    }
    
    // Fall thru to fast mode for smaller numbers
    // assert(i <= 65536, i);
    //       
    for (;;) {
    //   i*(52429/524288)=i*0.10000038146972656=i*0.1=i/10
    //    52429   2 19    ,          ,      i/10   
    //        ,                >      >     
    q = (i * 52429) >>> (16+3);
    r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
    buf [--charPos] = digits [r];
    i = q;
    if (i == 0) break;
    }
    if (sign != 0) {
    buf [--charPos] = sign;
    }
    }
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기