java.lang.Integer 源码深入解读
来源:互联网 发布:软件下载引导页源码 编辑:程序博客网 时间:2024/06/05 02:48
最近算是比较深入的了解了一下Integer的源码,就想着写点东西记录一下,一来可以加深理解,再来也算是为我刷了那么久segmentfault平台贡献一点自己的绵薄之力。
一、构造函数:
解读一个类的源码我喜欢从构造函数入手,这里先上Integer的构造源码:
public Integer(int value) { this.value = value;}public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10);}
在Integer类中提供了两个构造函数,分别针对构造参数为基本类型int和引用类型String。这两个方法都是给当前的实例的value属性赋值,参数为int类型的构造器直接将参数赋值给value属性,参数为String是将parseInt(String s, int radix)方法的返回值赋值。JDK1.5之后,java提供了自动装箱和自动拆箱的功能。自动装箱也就是调用了Integer类的一个静态方法valueOf方法,先看源码:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}
源码中有一个IntegerCache,这一个私有的内部类。这个类缓存了low - high之间数字的包装类。关于这个类的分析在下面,反正你需要记住它把一些数字的包装类提前缓存了,如果判断成立就把缓存中的那个包装类返回,如果不则new一个新的。这里也就明白了下面问题的原因了:
Integer a = 100;Integer b = 100;Integer c = 200;Integer d = 200;System.out.println(a == b);//trueSystem.out.println(c == d);//false
通过javap -c/javap -verbose 命令可以查看字节码;红色圈圈里就是我们jdk5之后的基本类型的自动包装的字节码实现,可以看出,此处是调用了Integer.valueOf(..)方法的:说白了就是Integer a = 100 等价于Integer a = Integer.valueOf(100)
二、IntegerCache:
先上源码:
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); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }
以上可以知道这个类是私有的且是静态的,并且他有三个被final修饰的静态filed外加一个静态块和一个私有的构造器;很简单很普通的一个类,被缓存的包装类就介于low - high之间,low的值已经写死-128,而high的值由你的虚拟机决定sun.misc.VM.getSavedProperty(“java.lang.Integer.IntegerCache.high”),既然是一个参数也就意味着你可以动态设置,具体怎么设置自行百度。然后在循环中将low - high之间数字的装箱后方法cache[]这个Integer类型的数组中。这样就完成了缓存。
三、toString(int i): 照例先上源码:
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]; getChars(i, size, buf); return new String(buf, true);}
这个方法内部调用了两个方法:stringSize和getChars,toString方法的实现也就是由这两个方法合作完成,stringSize实现上很是比较简单的,源码我就不上了,它是用来计算参数i的位数也就是转成字符串之后的字符串的长度。内部结合一个已经初始化好的int类型的数组sizeTable来完成这个计算。稍动头脑就能想明白,很巧妙的一个方法。然后来说说toString这个方法实现的最大功臣getChars这个方法,上源码:
static void getChars(int i, int index, char[] buf) { int q, r; int charPos = index; char sign = 0; if (i < 0) { sign = '-'; i = -i; } // Generate two digits per iteration while (i >= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; buf [--charPos] = DigitOnes[r]; buf [--charPos] = DigitTens[r]; } // Fall thru to fast mode for smaller numbers // assert(i <= 65536, i); for (;;) { q = (i * 52429) >>> (16+3); r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... buf [--charPos] = digits [r]; i = q; if (i == 0) break; } if (sign != 0) { buf [--charPos] = sign; }}
三个参数:i:被初始化的数字,index:这个数字的长度(包含了负数的符号“-”),buf:字符串的容器-一个char型数组。第一个if判断,如果i<0,sign记下它的符号“-”,同时将i转成整数。下面所有的操作也就只针对整数了,最后在判断sign如果不等于零将sig你的值放在char数组的首位buf [–charPos] = sign;。 最后来分析方法中的两个循环:while和for,其实这两个循环做的事情一样。只是while循环来处理i>65535的情况,且每次取两位数:
buf [–charPos] = DigitOnes[r];
buf [–charPos] = DigitTens[r];
剩下的情况由for循环处理,且每次去一个数字。至于为什么这么做:// Fall thru to fast mode for smaller numbers,这是官方注释,意思就是真对小的数字使用快速方式。针对这块的理解我也是参考了知乎上的网友的回答java源码中Integer.class中有个getChars方法,里面有个52429是怎么确定的? 表示感谢。
至此Integer类的核心也就完了。就这吧!
- java.lang.Integer 源码深入解读
- Java Integer源码解读
- java源码解读之Integer
- java.lang.Integer源码分析
- Java源码侦探-Integer方法解读
- 【JDK】:java.lang.Integer源码解析
- 【实践】java.lang.Integer源码分析
- 【实践】java.lang.Integer源码分析 -- parseInt
- 【实践】java.lang.Integer源码分析 -- valueOf
- java 十六进制 Integer 进制转换 源码解读
- 完全解读 Java中的 Integer.bitCount(int i)源码
- Glance源码深入解读
- OkHttp源码深入解读
- java.lang.Integer翻译
- EXception :java.lang.Integer
- 02 java.lang.Integer
- java.lang.Integer常见问题
- java.lang.Integer
- python 在jailbreak 的iOS设备上运行,出现kill:9 处理办法
- ProGuard详解
- 解决遗忘linux登陆密码
- 浅谈UDP(数据包长度,收包能力,丢包及进程结构选择)
- spring boot 部署老的weblogic
- java.lang.Integer 源码深入解读
- 《第一行代码》Service学习笔记
- js切换图片方式形成动画
- 【字符串】【扩展kmp算法总结~~】
- 简单处理Problem 3223. -- Tyvj 1729 文艺平衡树
- 004_JS封装简单动画函数
- zoj1151 zoj1295 Word Reversal 字符串的简单处理
- 一次陈旧项目的升级发布之路
- [数据挖掘]利用Titanic学习特征工程