Integer源码分析。
public final class Integer extends Number implements Comparable<Integer> {
/*
* 继承Number类提供将表示的数值转换为 byte、double、float、int、long 和 short 的方法。<br />
* 实现Comparable接口,获取到compareTo方法。
*/
// 值为 -231 的常量,它表示 int 类型能够表示的最小值。
public static final int MIN_VALUE = 0x80000000;
// 值为 2的31方-1 的常量,它表示 int 类型能够表示的最大值
public static final int MAX_VALUE = 0x7fffffff;
// 表示基本类型 int 的 Class 实例
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
// 用于将数字表示为字符串的所有可能字符,支持二进制到三十六进制(故需要36个字符)
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
/**
* 转化对应进制的数字为十进制
* @param i 要转换成字符串的整数
* @param radix 进制数
* @return String
*/
public static String toString(int i, int radix) {
// 如果进制数小于2进制 或者大于 26进制,则改用十进制。
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
/* 如果是十进制,用最快的版本 */
if (radix == 10) {
return toString(i);
}
// 创建一个33位的字符数组(负数时:1位符号位+32位数字;正数时,32位数字)
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
// 将正数转为负数进行运算,防止负数转为正数的溢出情况
if (!negative) {
i = -i;
}
// 循环判断当前转换的字符是否小于计数的相反数
while (i <= -radix) {
// //根据余数的相反数在digits数组中获取相应的字符,倒序存放到buf[]数组里
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
// 若是负数,加减号
if (negative) {
buf[--charPos] = '-';
}
// 返回一个字符串,参数为char数组、起始位置、字符长度
return new String(buf, charPos, (33 - charPos));
}
/**
* 返回当前整数的16进制的字符串形式
* @param i 要转换成字符串的整数
*/
public static String toHexString(int i) {
return toUnsignedString(i, 4);
}
/**
* 返回当前整数的8进制的字符串形式
* @param i 要转换成字符串的整数
* @return String
*/
public static String toOctalString(int i) {
return toUnsignedString(i, 3);
}
/**
* 返回当前整数的2进制的字符串形式
* @param i 要转换成字符串的整数
* @return String
*/
public static String toBinaryString(int i) {
return toUnsignedString(i, 1);
}
/**
* 返回当前整数i的shift进制的字符串形式的私有工具类
* @param i 要转换成字符串的整数
* @param shift 进制数
* @return String
*/
private static String toUnsignedString(int i, int shift) {
// 当shift为1二进制时,char数组大小32刚好,而当shift为3,4时,数组大小有余
char[] buf = new char[32];
// 当数组有余时,便于取char数组中的数据
int charPos = 32;
// 算数左移,radix中间变量用于计算mask
int radix = 1 << shift;
// mask掩码用于获取i的shift位低位,mask二进制数每一位都是1
int mask = radix - 1;
do {
//取出i二进制数低位shift位,将对应的字符存入buf
//新建数组大小时[]填32,但是在数组赋值时[]填0~31
buf[--charPos] = digits[i & mask];
//逻辑右移,剔除已取出的shfit位低位
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
/**
* DigitTens和DigitOnes这两个常量数组主要是为了获取0到99之间某个数的十位和个位。
*/
//取十位数
final static char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
// 取个位数
final static char [] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
/**
* 返回当前数字的字符串形式
* @param i 十进制的整数
* @return String
*/
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
// 判断是否为负数,计算长度
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
// 将数字分成一个个char,保存到buf数组中
getChars(i, size, buf);
return new String(buf, true);
}
/**
* 将某个int型数值写入到字符数组中(若i等于Integer.MIN_VALUE,则为失败)
* 该方法将int进行高两字节、低两字节分开处理
* 几种运算的耗时长短:除法运算>乘法运算>移位结合加法的运算
* @param i 需要处理的整数
* @param index 整数长度
* @param buf 字符数组
* @return void
*/
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
// 是否为负数,则将标志符号设为减号,然后i取相反数
if (i < 0) {
sign = '-';
i = -i;
}
// 处理高两字节
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2));
// 将商赋给i,继续循环,直到小于65536
i = q;
// 取DigitOnes[r]的值其实取数字r%10的结果
buf [--charPos] = DigitOnes[r];
// 取DigitTens[r]的值其实取数字r/10的结果
buf [--charPos] = DigitTens[r];
}
// 对于较小的数字,进入快速模式
// 循环存放低两字节的数字存放到字符数组中空余位置
for (;;) {
// 右移19位
/**
* >>>: 无符号的右移
* >>: 有符号的右移
*/
// q=i/10
q = (i * 52429) >>> (16+3);
// r = i-(q*10)
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
// 从digit数组中取数
buf [--charPos] = digits [r];
i = q;
//整数写入字符数组完成
if (i == 0) break;
}
//若整数是负数,需要在字符数组中加上'-'字符
if (sign != 0) {
buf [--charPos] = sign;
}
}
// 用在判断一个int类型数字对应字符串的长度
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
/**
* 判断一个int类型数字的长度
* 要求正数
* @param x int类型的正整数
* @return
*/
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
/**
* 返回输入字符串的指定进制的正整数
* @param s 需要转换的字符串
* @param radix 当前字符串的数字部分的进制数(也就是s的进制)
* @return int
*/
public static int parseInt(String s, int radix)
throws NumberFormatException
{
/*
* 警告:此方法可以在VM初始化的早期调用
* 在初始化IntegerCache之前。注意不要使用方法的值。
*/
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 limit = -Integer.MAX_VALUE;
int multmin;
int digit;
//字符串长度大于0
if (len > 0) {
// 获取字符串的第一个字符
char firstChar = s.charAt(0);
// 如果第一个字符小于0
if (firstChar < '0') {
if (firstChar == '-') { // 负数
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+') //不为正数
throw NumberFormatException.forInputString(s);
// 输入的转化字符串只有一个"+"或"-"
if (len == 1)
throw NumberFormatException.forInputString(s);
i++;
}
// 限制的最小值(在对应进制的)
multmin = limit / radix;
// 将字符串的数字部分转为进制的数字(从左到右)
while (i < len) {
// 将字符串的数字部分的一个数字(对应进制),通过Character类转为进制的数
// 若字符串中的某一个字符,在字符串进制下(radix)是无效的,则返回-1
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {// 若返回-1(无效)
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;
}
/**
* 返回指定字符串的int类型的数值,默认是10进制的
* @param s 需要转换的字符串
* @return int
*/
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
/**
* 返回指定转换进制的字符串的一个Integer对象
* @param s 需要转换的字符串
* @param radix 进制位
* @return Integer
*/
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
/**
* 返回指定字符串的一个Integer对象,默认是10进制的
* @param s 需要转换的字符串
* @return Integer
*/
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
/**
* 缓存以支持自动装箱的对象标识语义,用于在-128和127(包括JLS要求的)。
* 缓存在第一次使用时被初始化。缓存大小
* 可以通过-XX:AutoBoxCacheMax=<size>选项进行控制。
* 在VM初始化期间,java.lang.Integer.IntegerCache.high属性
* 可以在Sun.misc.VM类。
*/
private static class IntegerCache {
static final int low = -128;
// 高值可以通过属性配置:启动JVM时通过 -Djava.lang.Integer.IntegerCache,high=xxx进行设置
static final int high;
static final Integer cache[];
static {
// 可以通过属性配置高值
int h = 127;
// 读取JVM初始化时的属性
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// 最大数组大小是Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low));
}
// 未配置则为默认最高值127
high = h;
// 创建一个大小为(最大值-最小值+1)的数组
cache = new Integer[(high - low) + 1];
int j = low;
// 创建对应大小的Integer对象,放入缓存的数组中
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
/**
* 返回一个表示指定的 int 值的 Integer 实例。
* 如果不需要新的 Integer 实例,则通常应优先使用该方法,
* 而不是构造方法 Integer(int),因为该方法有可能
* 通过缓存经常请求的值而显著提高空间和时间性能。
* @param i 指定的int值
* @return Integer
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
// 直接获得在[low,high]范围内的IntegerCache缓存的Integer对象,不在该范围则重新实例化Integer对象
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
// 保存Integer类中的真实基本数据类型的值
private final int value;
/**
* 构造一个新分配的 Integer 对象,它表示指定的 int 值。
* @param value
*/
public Integer(int value) {
this.value = value;
}
/**
* 构造一个新分配的 Integer 对象,
* 它表示 String 参数所指示的 int 值。
* 使用与 parseInt 方法(对基数为 10 的值)相同的方式将该字符串转换成 int 值。
* @param s 指定的int值
* @throws NumberFormatException
*/
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
/**
* 以 byte 类型返回该 Integer 的值。
*/
public byte byteValue() {
return (byte)value;
}
/**
* 以 short 类型返回该 Integer 的值。
*/
public short shortValue() {
return (short)value;
}
/**
* 以 int 类型返回该 Integer 的值。
*/
public int intValue() {
return value;
}
/**
* 以 long 类型返回该 Integer 的值。
*/
public long longValue() {
return (long)value;
}
/**
* 以 float 类型返回该 Integer 的值。
*/
public float floatValue() {
return (float)value;
}
/**
* 以 double 类型返回该 Integer 的值。
*/
public double doubleValue() {
return (double)value;
}
/**
* 返回一个表示该 Integer 值的 String 对象。
* 将该参数转换为有符号的十进制表示形式,
* 并以字符串的形式返回它,
* 就好像将该整数值作为参数赋予 toString(int) 方法一样。
*/
public String toString() {
return toString(value);
}
/**
* 返回此 Integer 的哈希码
*/
public int hashCode() {
return value;
}
/**
* 比较此对象与指定对象。当且仅当参数不为 null,
* 并且是一个与该对象包含相同 int 值的 Integer 对象时,
* 结果为 true。
*/
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
/**
* 返回系统常量的int值,类似System.getProperty(str);
* @param nm 属性名
* @return Integer
*/
public static Integer getInteger(String nm) {
return getInteger(nm, null);
}
/**
* 返回系统常量的int值,类似System.getProperty(str);
* 如果为空,默认值为val
* @param nm 属性名
* @param val 给定默认值
* @return Integer
*/
public static Integer getInteger(String nm, int val) {
Integer result = getInteger(nm, null);
return (result == null) ? Integer.valueOf(val) : result;
}
/**
* 返回具有指定名称的系统属性的整数值。
* @param nm 属性名
* @param val 给定默认值
* @return Integer
*/
public static Integer getInteger(String nm, Integer val) {
String v = null;
try {// 获取对应系统变量名的值
v = System.getProperty(nm);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
}
if (v != null) {
try {//返回字符串中的数字
return Integer.decode(v);
} catch (NumberFormatException e) {
}
}
return val;
}
/**
* 解码字符串转成Integer型对象
* @param nm 要解码的 String
* @throws NumberFormatException
* @return Integer
*/
public static Integer decode(String nm) throws NumberFormatException {
// 十进制
int radix = 10;
// 当前判断完的字符数
int index = 0;
boolean negative = false;
Integer result;
if (nm.length() == 0)
throw new NumberFormatException("Zero length string");
// 获得字符串的第一个字符
char firstChar = nm.charAt(0);
if (firstChar == '-') {// 如果为负
negative = true;
index++;
} else if (firstChar == '+')//为"+"的情况
index++;
// 然后剩下的字符串以0x或0X开头,表示十六进制
if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (nm.startsWith("#", index)) {//或以#开头,表示十六进制
index ++;
radix = 16;
}
//若以0开头,且字符串长度大于当前判断字符数+1,,则为8进制
else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
index ++;
radix = 8;
}
// 再存在"-"/"+"这两字符,则抛出数字转化异常
if (nm.startsWith("-", index) || nm.startsWith("+", index))
throw new NumberFormatException("Sign character in wrong position");
try {
// 将剩下的字符串从某进制转为指定进制的数的包装类对象
result = Integer.valueOf(nm.substring(index), radix);
// 若是负数,取反包装类Integer中的value的值,再进行获取该基本数据类型的包装对象实例
result = negative ? Integer.valueOf(-result.intValue()) : result;
} catch (NumberFormatException e) {
// 使用int类型参数转化出现异常,转而使用String类型参数进行转化
String constant = negative ? ("-" + nm.substring(index))
: nm.substring(index);
// 转化字符串成对应的包装类的实例对象
result = Integer.valueOf(constant, radix);
}
return result;
}
/**
*比较两个 Integer 对象的value值大小
*/
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
/**
* 比较两个int类型的值的大小
* @param x
* @param y
* @return int
*/
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
/**
* 静态常量SIZE用来表四二进制补码形式的int值的比特数,值为32
*/
public static final int SIZE = 32;
/**
* 返回在二进制情况下,i的最高位为1,其他全为0的值。
* 将31位都置为1,然后将该值减去该值右移一位的值
* @param i
* @return int
*/
public static int highestOneBit(int i) {
//右移一位或上原值
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
//i值减去i右移一位的值
return i - (i >>> 1);
}
/**
* 获取最低位为1,其他位都为0的值
* @param i
* @return int
*/
public static int lowestOneBit(int i) {
// 先取负数(对正数的i取反码然后加1),得到的结果和i进行与操作。
return i & -i;
}
/**
* 返回i的二进制从头开始有多少个0
* @param i
* @return int
*/
public static int numberOfLeadingZeros(int i) {
//i为0,则有32个0
if (i == 0)
return 32;
int n = 1;
// 使用二分查找(也就是折半查找)思想,看右移16、24、28、30、31位的结果是否为0
if (i >>> 16 == 0) { n += 16; i <<= 16; }
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
n -= i >>> 31;
return n;
}
/**
* 返回i的二进制从尾开始有多少个0
* 基于二分查找
* @param i
* @return int 返回类型
*/
public static int numberOfTrailingZeros(int i) {
int y;
if (i == 0) return 32;
int n = 31;
y = i <<16; if (y != 0) { n = n -16; i = y; }
y = i << 8; if (y != 0) { n = n - 8; i = y; }
y = i << 4; if (y != 0) { n = n - 4; i = y; }
y = i << 2; if (y != 0) { n = n - 2; i = y; }
return n - ((i << 1) >>> 31);
}
/**
* 计算二进制数中1的个数
* @param i
* @return int
*/
public static int bitCount(int i) {
// 每两位一组统计看有多少个1
// 0x55555555也就是01010101010101010101010101010101
i = i - ((i >>> 1) & 0x55555555);
// 每四位一组统计看有多少个1
// 0x33333333也就是110011001100110011001100110011
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
// 每八位的1的个数
// 0x0f0f0f0f也就是00001111000011110000111100001111
i = (i + (i >>> 4)) & 0x0f0f0f0f;
// 每16位
i = i + (i >>> 8);
// 每32位
i = i + (i >>> 16);
// 最终与0x3f进行与运算,得到的结果,就是1的个数
return i & 0x3f;
}
/**
* 返回根据指定的位数循环左移指定的 int 值的二进制补码表示形式而得到的值。
* (位是从左边(即高位)移出,从右边(即低位)再进入)
* 注意,使用负距离的左循环等同于右循环:
* rotateLeft(val, -distance) == rotateRight(val, distance)。
* 还要注意的是,以 32 的任何倍数进行的循环都是无操作指令,
* 因此,即使距离为负,除了最后五位外,
* 其余所有循环距离都可以忽略:
* rotateLeft(val, distance) == rotateLeft(val, distance & 0x1F)。
* @param i
* @param distance
* @return int
*/
public static int rotateLeft(int i, int distance) {
return (i << distance) | (i >>> -distance);
}
/**
* 返回根据指定的位数循环右移指定的 int 值的二进制补码表示形式而得到的值。
* (位是从右边(即低位)移出,从左边(即高位)再进入)
* 注意,使用负距离的右循环等同于左循环:
* rotateRight(val, -distance) == rotateLeft(val, distance)。
* 还要注意的是,以 32 的任何倍数进行的循环都是无操作指令,
* 因此,即使距离为负,除了最后五位外,
* 其余所有循环距离都可以忽略:
* rotateRight(val, distance) == rotateRight(val, distance & 0x1F)。
* @param i
* @param distance
* @return int
*/
public static int rotateRight(int i, int distance) {
return (i >>> distance) | (i << -distance);
}
/**
* 对i进行反转,反转也就是第1位和第32位对调,第2位和第31位对调等
* @param i
* @return int
*/
public static int reverse(int i) {
// 将相邻两位进行对调
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
// 将相邻四位进行对调
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
// 将相邻的八位进行对调
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
// 32位中的中间16对调,最高八位和最低八位对调
i = (i << 24) | ((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) | (i >>> 24);
return i;
}
/**
* 返回指定 int 值的符号函数。(如果指定值为负,则返回 -1;
* 如果指定值为零,则返回 0;如果指定的值为正,则返回 1。)
* @param i
* @return int
*/
public static int signum(int i) {
// HD, Section 2-7
return (i >> 31) | (-i >>> 31);
}
/**
* 返回通过反转指定 int 值的二进制补码表示形式中字节的顺序而获得的值
* @param i
* @return int
*/
public static int reverseBytes(int i) {
return ((i >>> 24) ) | // 第1字节
((i >> 8) & 0xFF00) | // 第2字节
((i << 8) & 0xFF0000) | // 第3字节
((i << 24)); // 第4字节
}
// 序列号
private static final long serialVersionUID = 1360826667806852920L;
}
参考
Jdk1.6API
https://blog.csdn.net/tree_ifconfig/article/details/82387579
还没有评论,来说两句吧...