Integer 原码解读
有一天,突然发现,阅读原码可以发现很多有趣的东西。在Java中,我们知道很多东西都是封装好的,拿来即用,当你有一天去研究它拿来的东西是如何具体操作的,将会是非常有趣的事情。
在上一篇研究HashMap 源码的时候,发现了将任意大于某个数字的最小二次幂的实现,发现别人写的不仅漂亮而且高效。
在Java 的底层,很多高效的算法包含其中,阅读源码是非常有帮助的。
接下来将开始阅读 Integer 的源码,让自己更多的理解Integer 这个类的实现。
一.Integer 中的进制转换,包括将十进制转换为二进制及、八进制、十六进制
1.调用方法
Integer.toBinaryString()
Integer.toOctalString()
Integer.toHexString()
2.实现方法
转换为二进制
public static String toBinaryString(int i) {
return toUnsignedString0(i, );
} 转换为八进制
public static String toOctalString(int i) {
return toUnsignedString0(i, );
} 转换为十六进制
public static String toHexString(int i) {
return toUnsignedString0(i, );
}
3.底层实现
发现所有的进制转换都是调用的 toUnsignedString0() 这个方法,其实现如下
方法调用一
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
int chars = Math.max(((mag + (shift - )) / shift), );
char[] buf = new char[chars]; formatUnsignedInt(val, shift, buf, , chars); // Use special constructor which takes over "buf".
return new String(buf);
} 方法调用二
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = << shift;
int mask = radix - ;
do {
buf[offset + --charPos] = digits[val & mask];
val >>>= shift;
} while (val != && charPos > ); return charPos;
} 方法调用三
final static char[] digits = {
'' , '' , '' , '' , '' , '' ,
'' , '' , '' , '' , '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'
};
二. Integer 中的方法
方法1:比较2个数字的大小,若 第一个小于第二个,返回-1;若相等,返回0;若第一个大于第二个,返回1
public static int compare(int x, int y) {
return (x < y) ? - : ((x == y) ? : );
}
方法2: 返回该数字二进制 补码中 1 的个数
public static int bitCount(int i) {
// HD, Figure 5-2
i = i - ((i >>> ) & 0x55555555);
i = (i & 0x33333333) + ((i >>> ) & 0x33333333);
i = (i + (i >>> )) & 0x0f0f0f0f;
i = i + (i >>> );
i = i + (i >>> );
return i & 0x3f;
}
方法3: 返回String 或者 int 类型的 Integer 实例
第一步:
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, ));
} 第二步:
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 = ;
boolean negative = false;
int i = , len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit; if (len > ) {
char firstChar = s.charAt();
if (firstChar < '') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s); if (len == ) // 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 < ) {
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;
} 第三步:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
方法4:将String 类型转换为 Int 类型
输入String
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,);
} parseInt() 调用方法同上
Integer 原码解读的更多相关文章
- python skimage库HOG特征提取原码解读
Hog特征+SVM常用来做行人检测. opencv中也有Hog特征提取的原码,但是由于原码不是用python写的,而skimage用python实现了,所以就解读的skimage的代码. 先看用ski ...
- task_struct原码解读
该结构体在linux中的路径为如下,如果是本地也可以根据以下子目录找到task_struct结构体,该结构体源码中在600多行 https://github.com/torvalds/linux/bl ...
- 进制,原码VS补码
进制 十,八,十六进制=>二进制 十进制=>二进制:辗转相除取余,10除2商5余0,5除2商2余1,2除2商1余0,1除2商0余1,So,10d=1010b 八进制=>二进制:每1位 ...
- 【原】Spark不同运行模式下资源分配源码解读
版权声明:本文为原创文章,未经允许不得转载. 复习内容: Spark中Task的提交源码解读 http://www.cnblogs.com/yourarebest/p/5423906.html Sch ...
- 【原】Spark中Job的提交源码解读
版权声明:本文为原创文章,未经允许不得转载. Spark程序程序job的运行是通过actions算子触发的,每一个action算子其实是一个runJob方法的运行,详见文章 SparkContex源码 ...
- 【原】SparkContex源码解读(二)
版权声明:本文为原创文章,未经允许不得转载. 继续前一篇的内容.前一篇内容为: SparkContex源码解读(一)http://www.cnblogs.com/yourarebest/p/53266 ...
- jdk1.8.0_45源码解读——ArrayList的实现
jdk1.8.0_45源码解读——ArrayList的实现 一.ArrayList概述 ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素. ...
- MyBatis源码解读之延迟加载
1. 目的 本文主要解读MyBatis 延迟加载实现原理 2. 延迟加载如何使用 Setting 参数配置 设置参数 描述 有效值 默认值 lazyLoadingEnabled 延迟加载的全局开关.当 ...
- JDK容器类List,Set,Queue源码解读
List,Set,Queue都是继承Collection接口的单列集合接口.List常用的实现主要有ArrayList,LinkedList,List中的数据是有序可重复的.Set常用的实现主要是Ha ...
随机推荐
- html内容溢出部分...
首先标签必须满足不是行内标签 方法一:(单行)此方法没有任何问题 width: 38px;(需要给定宽度) overflow: hidden; white-space: nowrap; text-ov ...
- OpenGL中摄像机矩阵的计算原理
熟悉OpenGL|ES的朋友,可能会经常设置摄像机的view矩阵,iOS中相对较好,已经封装了方向,只需要设置摄像机位置,目标点位置以及UP向量即可.下面先介绍下摄像机view矩阵的计算原理.此处假设 ...
- 白鹭引擎 - 碰撞检测 ( hitTestPoint )
1, 矩形碰撞检测 class Main extends egret.DisplayObjectContainer { /** * Main 类构造器, 初始化的时候自动执行, ( 子类的构造函数必须 ...
- ThinkCentre进入BIOS,设置intel virtualization technology
VMware安装提示cpu虚拟化intel virtualization technology ThinkCentre重启长按F1 按enter,开启intel virtualization tech ...
- 通过HTTP请求响应过程了解HTTP协议
通过HTTP请求响应过程了解HTTP协议 http://www.cnblogs.com/YeChing/p/6337378.html
- springboot 多环境选择
1.配置开发环境(开发环境) 2. application.yml 环境选择 3.cmd 切换环境 4. 设置环境调用方法 5. 另一方法
- 如何禁用Firefox,chrome浏览器“不安全密码警告”
在任何HTTP页面中,一个全新的“不安全密码警告”将会在用户点击表单时直接出现在登陆框的下方,强行保证所有用户都能看到“此链接不安全,你的个人利益将受到损害”等字眼,同时整个页面也会收到损坏的挂锁图标 ...
- mongo aggregate 用法记录
mongo 聚合查询查询还是很方便的,做下记录 依赖的jar是org.springframework.data.mongodb 1.9.6 低版本可能不支持. 数据结构 大概是 这是一份 ...
- gevent mysql
使用gevent实现mysql并发时,每个greenlet应该独享一个mysql连接,否则,不同的greenlet之间会相互影响. ultramysql doesn't allow you to ma ...
- Java读写hdfs上的avro文件
1.通过Java往hdfs写avro文件 import java.io.File; import java.io.IOException; import java.io.OutputStream; i ...