摘要:略
- static final int MAX_VALUE
- static final int MAX_VALUE
- static final Class< Integer > TYPE
- static char[] digits
- static int highestOneBit(int i)
- static int lowestOneBit(int i)
- static String toString(int i, int radix)
类关系图
Integer是Number家族中的一个类,另外还实现了Comparable接口,用于比较大小。
1 | public int compareTo(Integer anotherInteger) { |
一些重要点
自动拆箱与装箱
在jdk1.5之后,引入了自动装箱与拆箱的机制,能自动的将原始类型和其相应的对象类型相互转换。
例如,在1.5之前,我们必须要这样写
1 | Integer a = valueOf(3); |
例如,下面写法在1.5之后都是正确的
1 | Integer a = 3; //autobox |
-128~127的缓存
对于以下代码,初学者都应该知道,打印结果是false和true
1 | Integer a = new Integer(1); |
因为这是两个不一样的对象,虽然值相同,但她们的地址是不同的,所以 == 为false,equeal为真。
但下面的例子,打印结果却为都为true:
1 | Integer a = 1; |
因为这里产生了自动装箱的操作,需要从int包装为Integer,装箱操作会调用valueOf方法:
1 | public static Integer valueOf(int i) { |
首先会对 i 进行一个比较,如果在某个范围内,返回数组中的一个对象,否则直接new一个对象。那么,查看一下IntegerCache类,这是一个静态内部类:
1 | private static class IntegerCache { |
这个类中有三个成员变量,low、high和cache[],cache就是缓存所用到的数组,low定义了最小缓存的值,默认-128,high定义了最大缓存值,默认127。类中有一个静态代码块,主要是获取缓存的最大值(如果你有通过属性设置),之后呢,对cache数组进行初始化,任务就完成了。
缓存起一部分对象最大的好处就是能够节省内存,选择-128~127这个范围也是这个区间的发生装箱拆箱的频率最高。而且,大量的无用对象也会给GC造成不小的压力。
而我们直接new一个Integer对象的话,调用了构造函数,是不可能使用缓存的,Integer包装类为我们维护了一个int类型的变量,仅此而已。
1 | //这是Integer对象中维护的值,被final修饰,不可更改 |
一些字段
MIN_VALUE
1 | /** |
java中,int是32位的,MIN_VALUE 是int类型能表示的最小值,-2147483648,0x8000000是补码的表示形式。
MAX_VALUE
1 | /** |
MAX_VALUE 是int所能表示的最大的数,2147483647。
TYPE
1 | /** |
注意:
Integer.TYPE == int.class
Integer.TYPE != Integer.class
digits
1 | /** |
Integer类中,String toString(int i, int radix)方法可以将数字转成转成2至32进制中任意一个进制,返回结果就是String,这个digits数组,就是用来存储表示各个进制的的字符。
一些方法
static int highestOneBit(int i)
1 | /** |
读一下注释,可以理解,这个方法返回的是指定的某个数,从左到右开始(leftmost),第一个”1”后面的位数全部补0,返回其int结果。
举个栗子,这个函数的 i 传入 88888888,因为java 中 int 是32位的,她的值用二进制表示是:0000,0101,0100,1100,0101,0110,0011,1000,最左边的“1”右边全部清零,就变成了0000,0100,0000,0000,0000,0000,0000,0000,其int结果是2^26,等于67108864。
代码解读
函数只有简短五行代码(不算注释)。
- 把 i 右移一位,并与原数据按位取或,这样就使最高位1和她的下一位都变成了1;
- 把刚刚得到的两个1再右移两位,并与原数据按位取或,这样刚刚连续的两个1,就变成四个1了;
- 把刚刚的四个1右移四位,并与原数据按位取或,这样就得到八个连续的1了;
- 省略两步。结果是右移完16位后,最高位1和她右边的都是1;
- 最后 i 减去 i无符号右移1位的值,就得到结果。
因为最后一步是无符号右移,所以参数是负数得到的结果不是0,永远是0x80000000,也就是int的最小值
static int lowestOneBit(int i)
1 | /** |
和上面的方法很相似,这个方法返回的是指定的某个数,从右到左开始(rightmost),第一个”1”后面的位数全部补0,返回其int结果。我们依旧把 88888888 传入这个方法,那么得到的结果是 8。
算法很简单,将其与其的负数相与即可。因为这两个数有一个是负数,负数的补码是原码取反再加一,这就导致了最右边的1 位置是相同的。
static String toString(int i, int radix)
1 | public static String toString(int i, int radix) { |
这个方法注释有点长,没贴,功能是将数字,转成某种进制的字符串。参数 i 是需要转的数字,参数 radix 是进制数。
方法首先检查了radix的范围,因为10个数字,加26个字母,最多只能展示到36进制,最低当然是2进制,参数不处于这个范围的,用10进制代替,如果进制是10,那直接返回 tostring(int i) 。
int是32位的,再加上一个符号位,所以要33位的数组
之后的操作是将正数转成负数再进行计算,因为负数的最小值是-2147483648,正数最大值是2147483647,负数转正数的话可能会产生溢出。
再之后就是比较平常的进制转换算法了。