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, 所以请大家指出!
相关文章推荐
- 01 java.lang.Object
- java源码阅读笔记(1)- Object
- 10 java.lang.ThreadLocal
- 09 java.lang.Runtime
- 08 java.lang.ProcessBuilder
- 07 java.lang.StringBuilder
- 06 java.lang.AbstractStringBuilder
- 05 java.lang.String
- 04 java.lang.Byte
- 03 java.lang.Boolean
- 源码学习之ArrayList
- Closeable的作用
- Java依据Url下载图片
- java学习记录笔记--多态,接口,UML简介
- JAVA的简单计算器设计
- struts2 学习之 redirectAction初步认识
- Java Collection接口的常用方法
- java 设计类时考虑多线程安全
- Myeclipse 10 破解说明
- Struts、JSTL标签库的基本使用方法