java.lang.Integer源码精读(二)

分享不易,喜欢请点赞支持,谢谢

JDK源码精读汇总帖

getInteger()

然后比较少用的方法getInteger,这个方法是用来返回系统属性(String nm)的整数值的,很容易理解。

1public static Integer getInteger(String nm) { 2 return getInteger(nm, null); 3} 4public static Integer getInteger(String nm, int val) { 5 Integer result = getInteger(nm, null); 6 return (result == null) ? Integer.valueOf(val) : result; 7} 8public static Integer getInteger(String nm, Integer val) { 9 String v = null; 10 try { 11 v = System.getProperty(nm); 12 } catch (IllegalArgumentException e) { 13 } catch (NullPointerException e) { 14 } 15 if (v != null) { 16 try { 17 return Integer.decode(v); 18 } catch (NumberFormatException e) { 19 } 20 } 21 return val; 22}

decode(String)

看到上面的方法调用了decode方法,这个方法与valueOf和parseInt的区别就是后者只能分析字符串中是纯数字的,而decode可以分析类似0xff这种。

1/** 2 * 8进:010=>分析后为 8 3 * 10进:10=>分析后为 10 4 * 16进:#10|0X10|0x10=>分析后是 16 5 * 而valueOf 只能分析纯数字的String 6 * 注意:这里的nm已经对应的是上面的v了,不是系统属性的key了 7 */ 8public static Integer decode(String nm) throws NumberFormatException { 9 int radix = 10; 10 int index = 0; 11 boolean negative = false; 12 Integer result; 13 14 if (nm.length() == 0) 15 throw new NumberFormatException("Zero length string"); 16 char firstChar = nm.charAt(0); 17 // 符号处理 18 if (firstChar == '-') { 19 negative = true; 20 index++; 21 } else if (firstChar == '+') 22 index++; 23 24 // 进制处理 25 if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) { 26 index += 2; 27 radix = 16; 28 } 29 else if (nm.startsWith("#", index)) { 30 index ++; 31 radix = 16; 32 } 33 // 以0开头且长度不止1位的才当成8进制,否则可能就是一个0 34 else if (nm.startsWith("0", index) && nm.length() > 1 + index) { 35 index ++; 36 radix = 8; 37 } 38 39 if (nm.startsWith("-", index) || nm.startsWith("+", index))// 处理完前面的字符之后,还有'-'/'+',则为异常情况 40 throw new NumberFormatException("Sign character in wrong position"); 41 42 try { 43 result = Integer.valueOf(nm.substring(index), radix);// 截取标志位(0x等)之后的数字,如果是Integer.MIN_VALUE,将会被传入2147483648,会被valueOf抛出异常,所以需要在catch里再处理 44 result = negative ? Integer.valueOf(-result.intValue()) : result; 45 } catch (NumberFormatException e) { 46 // If number is Integer.MIN_VALUE, we'll end up here. The next line 47 // handles this case, and causes any genuine format error to be 48 // rethrown. 49 // 补回'-'变成-2147483648 给Integer.valueOf再处理 50 String constant = negative ? ("-" + nm.substring(index)) 51 : nm.substring(index); 52 result = Integer.valueOf(constant, radix); 53 } 54 return result; 55}

hashCode()

​ hashCode方法,直接返回value。

1public int hashCode() { 2 return value; 3}

equals()

​ equals方法比较value的比较。

1public boolean equals(Object obj) { 2 if (obj instanceof Integer) { 3 return value == ((Integer)obj).intValue(); 4 } 5 return false; 6}

highestOneBit(int)

​ highestOneBit这个函数返回的是数字i转换成二进制后最高位1对应的数值(10000....),即2^n对应的数字

1/** 2 * 返回最高位的1,1后面全补0对应的数,其实就是返回2^n 3 * 如果一个数是0, 则返回0; 4 *如果是负数, 则返回 -2147483648:【1000,0000,0000,0000,0000,0000,0000,0000】(二进制表示的数); 5 * 如果是正数, 返回的则是跟它最靠近的比它小的2的N次方 6 * 原理就是不停的右移再或运算,使得i最后变成从最高位1开始后面全是1,如11111...1 7 */ 8public static int highestOneBit(int i) { 9 // i右移1位在与i进行或运算,保证最高位两位都是1:11... 10 i |= (i >> 1); 11 // 这步完成之后,最高位4位都是1,1111... 12 i |= (i >> 2); 13 // 这步完成之后,最高位8位都是1,11111111... 14 i |= (i >> 4); 15 i |= (i >> 8); 16 i |= (i >> 16); 17 // 111...-011...到最高位的1,对应1000... 18 return i - (i >>> 1); 19}

lowestOneBit()

​ 然后是lowestOneBit,得到i最右边的1对应的数值,2^n的值。

1/** 2 * 这个方法很好理解,只考虑最右边1与它右边的数,最右边1与左边的数无需考虑。假设i最右边是100...0,不管1右边几个零,看看-i,反码为011..1,补码为1000,则i & -i ,1左边的都会变成0,1右边变成了100...0,正好得到最低位的1 3 */ 4public static int lowestOneBit(int i) { 5 // HD, Section 2-1 6 return i & -i; 7}

numberOfLeadingZeros()

​ 然后讨论numberOfLeadingZeros,这个方法的作用是返回参数i转成二进制后左边一共有多少个0。

1public static int numberOfLeadingZeros(int i) { 2 // 如果i是零,直接返回有32,代表二进制里32位都是零,java里int是4字节 3 if (i == 0) 4 return 32; 5 // 后面的逻辑完全是二分法的思维,判断i的第一个最左边的1在哪个位置,在判断过程中顺便累加了从左边开始0的个数,思路:先看你最左边1在高16位还是低16位,然后再判断你在16位中的高8位还是低8位,以此类推 6 int n = 1;// 0个数的计数器 7 // i右移16位之后有两种情况: 8 // 情况1:i==0;代表左边的1位于低16位,这样的话n+=16代表至少有16个零了。然后把i左移16位,这样情况1和情况2的后续处理方法就一致了。 9 // 情况2:i!=0;代表左边的1位于高16位,后续在高16位中继续判断 10 if (i >>> 16 == 0) { n += 16; i <<= 16; } 11 // 判断是否在低8位,在的话,0的个数加8,然后左移8位,后续与在高8位的情况同样处理 12 if (i >>> 24 == 0) { n += 8; i <<= 8; } 13 if (i >>> 28 == 0) { n += 4; i <<= 4; } 14 if (i >>> 30 == 0) { n += 2; i <<= 2; } 15 // 到这一步,所有情况都被当成是否在最高2位的情况处理了,这个时候n已经代表了0的个数 16 // 如果i>>>31为0,则在低1位,最左边还有1个0,正好是n初始化为1的理由 17 // 如果i>>>31为1,则在高1位,最左边没有0了,初始化n为1会导致多算1个0,n-1正好是0的个数 18 n -= i >>> 31; 19 return n; 20}

numberOfTrailingZeros()

​ numberOfTrailingZeros方法也是二分法的思想,返回最右边0的个数。

1public static int numberOfTrailingZeros(int i) { 2 // HD, Figure 5-14 3 int y; 4 if (i == 0) return 32; 5 int n = 31; 6 y = i <<16; if (y != 0) { n = n -16; i = y; } 7 y = i << 8; if (y != 0) { n = n - 8; i = y; } 8 y = i << 4; if (y != 0) { n = n - 4; i = y; } 9 y = i << 2; if (y != 0) { n = n - 2; i = y; } 10 return n - ((i << 1) >>> 31); 11}

分享不易,转载请注明出处

java.lang.Integer源码精读(二)
地址:https://www.jianshu.com/p/dc50508937c6

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java.lang.Integer源码精读(一)

分享不易,喜欢请点赞支持,谢谢JDK源码精读汇总帖(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.jianshu.com%2Fp%2F14092cfab6d9)

java.lang.Integer源码精读(二) - HelloWorld