您的位置:首页 > 编程语言 > Java开发

02 java.lang.Integer

2015-08-19 21:39 597 查看

Integer

2015.01.05&06&10
By 970655147


这个Integer的设计, 个人觉得还是非常有必要了解一下的, 后半部分的api, 涉及很多巧妙的位操作, 足矣让我们对位操作燃烧起浓厚的兴趣

start ->

声明

, 大家可以看看注释

/**
* The {@code Integer} class wraps a value of the primitive type
* {@code int} in an object. An object of type {@code Integer}
* contains a single field whose type is {@code int}.
*
* <p>In addition, this class provides several methods for converting
* an {@code int} to a {@code String} and a {@code String} to an
* {@code int}, as well as other constants and methods useful when
* dealing with an {@code int}.
*
* <p>Implementation note: The implementations of the "bit twiddling"
* methods (such as {@link #highestOneBit(int) highestOneBit} and
* {@link #numberOfTrailingZeros(int) numberOfTrailingZeros}) are
* based on material from Henry S. Warren, Jr.'s <i>Hacker's
* Delight</i>, (Addison Wesley, 2002).
*
* @author  Lee Boynton
* @author  Arthur van Hoff
* @author  Josh Bloch
* @author  Joseph D. Darcy
* @since JDK1.0
*/
public final class Integer extends Number implements Comparable<Integer>


Integer. toString(int i)

Integer. toString(int i)
public static String toString(int i) {
// 如果i是Integer.MIN_VALUE 则直接返回其字符串表示
if (i == Integer.MIN_VALUE)
return "-2147483648";
// 取得i的字符串表示的字符数 负数多一个“-”
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
// 根据i的值 获取其字符串表示
getChars(i, size, buf);
return new String(buf, true);
}

// 返回x的位数
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE };

// Requires positive x
static int stringSize(int x) {
for (int i=0; ; i++)
// 如果i<=9 则x的字符串表示位数为1
// 如果9<i<=99 则x的字符串表示位数为2
if (x <= sizeTable[i])
return i+1;
}

// 获取i的字符数组表示 用于toString()
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;

// 如果i是负数 sign为’-’ 并将i变为其相反数
if (i < 0) {
sign = '-';
i = -i;
}
// 循环直到i<65536 每一次循环计算的数减少两位
// Generate two digits per iteration
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
// r 为 i%100
r = i - ((q << 6) + (q << 5) + (q << 2));
// 更新i
i = q;
// 获取r[0<=r<100] 的个位字符串以及十位表示
buf [--charPos] = DigitOnes[r];
buf [--charPos] = DigitTens[r];
}

// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
// 每一次循环 计算的数减少一位
for (;;) {
// q = i*52429/524288  [i/10]
q = (i * 52429) >>> (16+3);
// r = i-(q*10)
// r = i%10
r = i - ((q << 3) + (q << 1));  ...
// 取得该位的字符串表示
buf [--charPos] = digits [r];
// 更新i
i = q;
// 如果I 变成0 跳出循环
if (i == 0) break;
}
// 如果i为负数 在符号表示前加上”-”
if (sign != 0) {
buf [--charPos] = sign;
}
}

关于i<65536的优化
因为2<<(16+3)=2<<19=524288,
(i * 52429)>>>(16+3) = i*52429/524288=
52429.0/524288=0.1000003814697......
6位的精度已经足够多了,所以就是i*0.1。
By  http://bbs.csdn.net/topics/90310030 
2^10=1024, 103/1024=0.1005859375
2^11=2048, 205/2048=0.10009765625
2^12=4096, 410/4096=0.10009765625
2^13=8192, 820/8192=0.10009765625
2^14=16384, 1639/16384=0.10003662109375
2^15=32768, 3277/32768=0.100006103515625
2^16=65536, 6554/65536=0.100006103515625
2^17=131072, 13108/131072=0.100006103515625
2^18=262144, 26215/262144=0.10000228881835938
2^19=524288, 52429/524288=0.10000038146972656

选19是在不超出整形范围内,精度最高的。
By  http://blog.csdn.net/wong_judy/article/details/5329715 
但是如果i超过了40595的话[超过2147483648] 会溢出啊
想了一下 无符号数Integer最大能表示4294967296[2 * 2147483648] – 1
所以上面的不会溢出
52429 * 65536 = 3435934515
65535 *52429/524288[0.10000038146972656] = 6553
by 970655147

2015.01.07


Integer.toString(int i, int radix)

public static String toString(int i, int radix) {
// 如果radix[基数]不合理[小于2或则大于36] 则取基数为10
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
// 如果基数是10 则直接返回i的字符串形式
/* Use the faster version */
if (radix == 10) {
return toString(i);
}

// 否则创建一个字符串数组存储对应I指定radix的表示字符串
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
// 如果i是正数 则将i转变为其相反值
if (!negative) {
i = -i;
}
// 循环箱该字符数组中存放i的指定基数的字符串表示 后 –> 前
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
// 放入最高位
buf[charPos] = digits[-i];
// 如果i是负数 在其字符串表示之前加上一个 “-”
if (negative) {
buf[--charPos] = '-';
}
// 返回该字符串表示
return new String(buf, charPos, (33 - charPos));
}


Integer. toUnsignedString(int i, int shift)

private static String toUnsignedString(int i, int shift) {
// 存储字符串表示的字符数组
char[] buf = new char[32];
int charPos = 32;
// 该基数的值
int radix = 1 << shift;
// 基数值-1
int mask = radix - 1;
do {
// i&mask  digit%radix
buf[--charPos] = digits[i & mask];
// i>>>=shift  i/radix
i >>>= shift;
} while (i != 0);

return new String(buf, charPos, (32 - charPos));
}

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);
}


Integer. parseInt(String s, int radix)

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");
}

// result 存储结果[计算的是s除去符号位,之后的正数的相反数]
// negative 存储是否s是负数
// i s从左至右的索引
// limit 最小值[正数的最大值是Integer.MAX_VALUE, 负数的最小值是Integer.MIN_VALUE]
// digit 表示s第i个字符的以radix为基数的数字表示
int result = 0;
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;

// 确保s的长度大于零
if (len > 0) {
char firstChar = s.charAt(0);
// 如果第一个字符 < ’0’[48] 则在真正的数值前可能有+/-号
if (firstChar < '0') {// Possible leading "+" or "-"
// 如果第一个字符是 ‘-’ 修改negative 以及limit
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
// 如果第一个字符不是’-’ 或 ‘+’ 那么s的格式有问题
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);
//如果第一个字符是’-’ 或 ‘+’ 但是s的长度为1 s格式有问题
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
// 如果result * radix >= limit 就会发生溢出
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
// result *= radix
result *= radix;
// 如果result – digit > limit 就会发生溢出
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
// s = 98, radix = 10
// loop1    result *= 10;   result -= -9        -9
// loop2    result *= 10;   result -= 8     -98
// result -= digit
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
// 如果s是负数 则直接返回,是正数则返回result的相反数
return negative ? result : -result;
}


Integer $IntegerCache[InnerClass]

// 存放常用的Integer对象[默认为-127~128]
// 还记得有一个2 + 2 = 5的漏洞么, 就是利用了IntegerCache
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage.  The size of the cache
* may be controlled by the -XX:AutoBoxCacheMax=<size> option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/

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);
// 如果配置的high小于127 则另h为127
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
// 将h赋值给high
high = h;
// 为缓存的Integer数组分配空间并初始化
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
// private constructor  only used by Integer
private IntegerCache() {}
}


Integer. valueOf(int i)

// 返回值为i的Integer对象
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
// 如果i在缓存的范围内 直接从缓存中取出对应的Integer
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
// 否则创建一个新的Integer对象
return new Integer(i);
}


Integer. byte/ short/ int/ long/ .. Value()

// 返回该Integer对象中的各种类型[byte, short, char, int, long, float, double]表示 基本上都是通过强制转换实现
public byte byteValue() {
return (byte)value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return value;
}
public long longValue() {
return (long)value;
}


Integer. hashCode()

public int hashCode() {
return value;
}


Integer. equals(Object obj)

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}


Integer. getInteger(String nm, Integer val)

// 获取名为nm的系统属性 val为默认值
public static Integer getInteger(String nm, Integer val) {
String v = null;
try {
// 获取名为nm的系统属性
v = System.getProperty(nm);
} catch (IllegalArgumentException e) {
} catch (NullPointerException e) {
}
// 若该属性不为null 返回其Integer对象
if (v != null) {
try {
return Integer.decode(v);
} catch (NumberFormatException e) {
}
}
// 返回默认值val
return val;
}


Integer. decode(String nm)

// 解析一个可以表示为Integer的字符串
public static Integer decode(String nm) throws NumberFormatException {
int radix = 10;         // 基数
int index = 0;          // nm的索引[当前便利到哪里去了]
boolean negative = false;   // 是否为负
Integer result;         // 保存结果
// 长度==0 格式不正确
if (nm.length() == 0)
throw new NumberFormatException("Zero length string");
char firstChar = nm.charAt(0);
// 判断正负
// Handle sign, if present
if (firstChar == '-') {
negative = true;
index++;
} else if (firstChar == '+')
index++;
// 根据字符串首部确定基数
// Handle radix specifier, if present
if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (nm.startsWith("#", index)) {
index ++;
radix = 16;
}
else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
index ++;
radix = 8;
}
// 如果 +[0x/0]+/+-/--/-+ 报告格式错误
if (nm.startsWith("-", index) || nm.startsWith("+", index))
throw new NumberFormatException("Sign character in wrong position");

try {
// 取除了符号位,基数表示为 之后的数值位的Integer表示
result = Integer.valueOf(nm.substring(index), radix);
// 正负处理
result = negative ? Integer.valueOf(-result.intValue()) : result;
} catch (NumberFormatException e) {
// If number is Integer.MIN_VALUE, we'll end up here. The next line
// handles this case, and causes any genuine format error to be
// rethrown.
// 如果s 是Integer.MIN_VALUE   因为Integer.MIN_VALUE= -2147483648 我们所取的是除了符号位,基数得到2147483648已溢出
String constant = negative ? ("-" + nm.substring(index))
: nm.substring(index);
result = Integer.valueOf(constant, radix);
}
return result;
}


Integer. compareTo(Integer anotherInteger)

public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}

public static int compare(int x, int y) {
// 如果前者大于后者返回1 相等返回0 否则返回-1
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}


* 好了, 接下来是精彩部分, 位操作来了 *

Integer. highestOneBit(int i)

// 返回将最高非0位右边所有的位变成0之后的值 2^n
public static int highestOneBit(int i) {
// HD, Figure 3-1
// 至少会将最高不为0位的右边1位变成1
i |= (i >>  1);
// 至少会将最高不为0位的右边2位的右边2位变成1
i |= (i >>  2);
i |= (i >>  4);
i |= (i >>  8);
i |= (i >> 16);
// 这样下来即使最高为是1 那么所有的转换下来最高位及其右边的位都成1了,这时候在减去 i>>>1 得到的就是原本[输入的i]的最高不为0位的右边的1全部变成0
// 如果是正数,原本[输入的i]的最高不为0位的右边的1全部变成0
// 如果是负数 得到的会是 -2147483648
// 3 -> 2       17 -> 16        18 -> 16        23 -> 16
return i - (i >>> 1);
}


Integer. lowestOneBit (int i)

// 返回将最低非0位左边所有的位变成0之后的值 2^n
public static int lowestOneBit (int i) {
// HD, Section 2-1
// 取反后的补码规则
// 最低非0位 右边所有的位均为0
// 各位取反 之后最低非0位右边所有的位均为1 刚才的最非0为变成0
// 在+1 低非0位 右边所有的位均为1 刚才的非0为 变成0 所以最低非0位 右边所有的位均为0,最低非0为又变成1
// 经过 & 运算只有改为变成1 其余所有为均为0
return i & -i;
}




Integer. numberOfLeadingZeros(int i)

// 计算i的最高非0为左边0的个数
public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
int n = 1;
// 如果i<2^16     i左移16,n+=16 此时i必然大于2^16
if (i >>> 16 == 0) { n += 16; i <<= 16; }
// 如果i<2^24     i左移24,n+=8  此时i必然大于2^24
if (i >>> 24 == 0) { n +=  8; i <<=  8; }
if (i >>> 28 == 0) { n +=  4; i <<=  4; }
if (i >>> 30 == 0) { n +=  2; i <<=  2; }
// 此时i的最高非0为 必然是在30/31/32位上
// 如果输入的i[没有经过左移]本身最高非0为在32为上 结果为1-1
// 其余的均为 n
n -= i >>> 31;
return n;
}


Integer. numberOfTrailingZeros(int i)

// 计算i的最低非0为右边0的个数 原理和上面一样,只不过用了一个y来缓存结果
public static int numberOfTrailingZeros(int i) {
// HD, Figure 5-14
int y;
if (i == 0) return 32;
int n = 31;
// 如果i左移16位>0       i左移16,n-=16 此时i必然大于2^16
y = i <<16; if (y != 0) { n = n -16; i = y; }
// 如果i左移8位>0        i左移8,n-=8   此时i必然大于2^24
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; }
// 此时i的最低非0为 必然是在30/31/32位上
// 如果输入的i[没有经过左移]本身最低非0为在32为上 结果为 31-0
// 其余的均为 n - 1
return n - ((i << 1) >>> 31);
}
2015.01.08


Integer. bitCount(int i)

// 统计i中有多少个位为1
public static int bitCount(int i) {
// HD, Figure 5-2
// 使用二分法 计算每两位之间有多少个1并将个数存储在这两位中
i = i - ((i >>> 1) & 0x55555555);
// 将两个两位中存放的1的个数相加 得到每四位中1的个数 并将数值存储在这四位中
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
// 将两个四位中存放的1的个数相加 得到每八位中1的个数 并将数值存储在这八位中
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
// 因为一个Integer 4byte = 32bit 最多存在32个1 截取前6为的数据即为1的个数
return i & 0x3f;
}










Integer. rotateLeft/ Right(int i, int distance)

// 将i左移distance位        如果distance<0 则将i右移distance Math.abs(distance)位
public static int rotateLeft(int i, int distance) {
// >>> num  如果num<0 则表达式为0
return (i << distance) | (i >>> -distance);
}

//将i无符号右移distance,如果distance为负,则左移-distance。负的肯定会移成正的。
public static int rotateRight(int i, int distance) {
return (i >>> distance) | (i << -distance);
}

2015.01.10


Integer. reverse(int i)

// 逆转其二进制的位 [按位]
public static int reverse(int i) {
// HD, Figure 7-1
// 相邻的两位交换
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
// 相邻的四位交换
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
// 相邻的八位交换
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
// 相邻的四个字节交换    完成逆转
i = (i << 24) | ((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) | (i >>> 24);
return i;
}




Integer. reverseBytes(int i)

// 逆转其二进制的位 [按字节]
public static int reverseBytes(int i) {
// 相邻的四个字节交换    完成逆转
return ((i >>> 24)           ) |
((i >>   8) &   0xFF00) |
((i <<   8) & 0xFF0000) |
((i << 24));
}




Integer. signum(int i)

// 判断输入整数的符号
public static int signum(int i) {
// HD, Section 2-7
// 如果i为正数   i>>31=1 -i>>>31=1
// 如果i为负数   i>>31=-1    -i>>>31=1
// 如果i为0        i>>31=0 -i>>>31=0
return (i >> 31) | (-i >>> 31);
}


-> end

ok, 到此Integer的分析就完毕了, 后半部分的位操作大家可以分析一下, 前半部分的当做文档查查就好了

还有 : Long和Integer的方法差不多 知识两者能表示的最大值最小值不同 这里就不赘述了

资源下载 : http://download.csdn.net/detail/u011039332/9025863

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java-源码