Integer
1.Integer声明
public final class Integer extends Number implements Comparable<Integer> {}
可以看到Integer类继承了Number类,而又不是抽象类,自然要重写Number类中的xxxValue方法。另外Integer类实现了Comparable接口,Comparable是一个接口,该接口定义类的自然顺序,实现该接口的类就可以按这种方式排序,一般情况下如果某类对象自身具有比较的特性就可以实现该接口,比如这里的Integer代表的是一种数,而数本身就具有比较的特性,就可以实现该接口。
2.Integer边界值
@Native public static final int MIN_VALUE = 0x80000000;
@Native public static final int MAX_VALUE = 0x7fffffff;
0x80000000 的2进制是1000,0000,0000,0000,0000,0000,0000,0000第一位是符号位,表示负的,后边是数值位,因为是负数,所以要取反计算,000,0000,0000,0000,0000,0000,0000,0000取反后111,1111,1111,1111,1111,1111,1111,1111,二进制是由补码表示,取补码为1000,0000,0000,0000,0000,0000,0000,0000,转为十进制是2^31,等于2147483648。因为是负数, 所以,0x80000000是-2147483648,int的最小值。
0x7fffffff 的2进制是0111,1111,1111,1111,1111,1111,1111,1111第一位是符号位,表示正数,正数反码和补码都等于原码为0111,1111,1111,1111,1111,1111,1111,1111,十进制是2^31-1, 所以,0x7fffffff是2147483647,int的最大值。
3.数组属性
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , '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'
};
final static char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
final static char [] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
digits数组用于表示所有可能出现的字符,所以这里需要有36个字符才能表示所有不同进制的数字 DigitTens和DigitOnes两个数组也很好理解,它们主要用于获取0到99之间某个数的十位和个位,比如36,通过DigitTens数组直接取出来十位为3,而通过DigitOnes数组取出来个位为6。 sizeTable数组主要用在判断一个int型数字对应字符串的长度。避免了使用除法或求余等操作,以提高效率。
4.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;
/* Use the faster version */
if (radix == 10) {
return toString(i);
}
//创建一个用于存放转换为指定字符的字符型数组,interger最大32位加上符号位
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
//全部转换位负数
if (!negative) {
i = -i;
}
while (i <= -radix) {
//i和进制取余为第一个数组数值,一直循环到不能循环为止
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
//将最后一个余数添加到数组
buf[charPos] = digits[-i];
//如果为负数添加符号
if (negative) {
buf[--charPos] = '-';
}
//buf转化为字符串
return new String(buf, charPos, (33 - charPos));
}
public static String toString(int i) {
//如果传入的值等于最小值直接返回
if (i == Integer.MIN_VALUE)
return "-2147483648";
//如果是负数,size等于stringSize(-i) + 1,加1为多一个符号位,否则等于 stringSize(i)
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
//计算出大小后。创建一个固定大小的char数组。
char[] buf = new char[size];
getChars(i, size, buf);
return new String(buf, true);
}
//利用之前说的数组值,直接计算大小,比如小于等于9肯定为1位数,依次类推,这样避免做除法带来的其他问题。
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
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
//如果大于65536
while (i >= 65536) {
//q等于i整除,其实就是取数的后两位之前的数
q = i / 100;
// really: r = i - (q * 100);
//明确的提示的就是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 (;;) {
//这个操作最终结果其实就是i/10
q = (i * 52429) >>> (16+3);
//这是i*10
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
//结果r为i的个位数,用数组取值插入buf
buf [--charPos] = digits [r];
//一直循环完所有个位数,最后一次i/10为0,跳出循环
i = q;
if (i == 0) break;
}
//如果为负数,插入数组第一个值为-号
if (sign != 0) {
buf [--charPos] = sign;
}
}
这个方法用于对参数转换为指定进制的字符串,里面有一些简单的设计比较可以学习。比如数组个位数和十位数,位运算都避免了除法操作。
5.toHexString(int i)
//转换为16进制
public static String toHexString(int i) {
return toUnsignedString0(i, 4);
}
//转换为8进制
public static String toOctalString(int i) {
return toUnsignedString0(i, 3);
}
//转换为2进制
public static String toBinaryString(int i) {
return toUnsignedString0(i, 1);
}
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 - 1)) / shift), 1);
char[] buf = new char[chars];
formatUnsignedInt(val, shift, buf, 0, chars);
// Use special constructor which takes over "buf".
return new String(buf, true);
}
//在指定 int 值的二进制补码表示形式中最高位(最左边)的 1 位之前,返回零位的数量
public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
//例子:假设有如下二进制数A是0000 1111 1111 1111 1111 1111 1111 1111,
int n = 1;
//如果高16位全部为0,n为17,低16位移动到高16位,例子不进if
if (i >>> 16 == 0) { n += 16; i <<= 16; }
//如果高24位全部为0,n为17,低24位移动到高24位,例子不进if
if (i >>> 24 == 0) { n += 8; i <<= 8; }
//如果高28位全部为0,n为17,低28位移动到高28位,例子进if,n为4+1=5,左移4位,所以要A变成 1111 1111 1111 1111 1111 1111 1111 0000
if (i >>> 28 == 0) { n += 4; i <<= 4; }
//如果高30位全部为0,n为17,低30位移动到高16位,例子不进if
if (i >>> 30 == 0) { n += 2; i <<= 2; }
//无符号右移31位后变成0000 0000 0000 0000 0000 0000 0000 0001,十进制表示为1,n -= i >>> 31;n -= 1;n = n - 1 = 5-1 = 4,说明前导0的个数是4
n -= i >>> 31;
return n;
}
static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
int charPos = len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[offset + --charPos] = Integer.digits[val & mask];
val >>>= shift;
} while (val != 0 && charPos > 0);
return charPos;
}
主要是用于10进制转换为其他进制的数据。
6.parseInt(String s, int radix)
public static int parseInt(String s, int radix)
throws NumberFormatException
{
// 第一步、判断字符串参数是否为null
if (s == null) {
throw new NumberFormatException("null");
}
// 第二步,判断基数是否小于最小基数 为2
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
// 第三步,判断基数是否大于最大基数 为36
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
// 标识,是否为负数,默认false
boolean negative = false;
// 字符串转换为char数组后的 下标和数组长度
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
// 第四步,判断字符串长度是不大于0
if (len > 0) {
// 取第一个字符
char firstChar = s.charAt(0);
/ 字符ASCII是否小于'0' ,可能为 '+' '-' , 如果不是<'0' ,则为数组 ,略过该if{}
if (firstChar < '0') { // Possible leading "+" or "-"
// 如果第一个字符是'-' ,说明是负数,则负数标识改为true ,限制改为最小标识
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
// 如果第一个字符不是'-' 也不是'+' ,异常
throw NumberFormatException.forInputString(s);
// 第一字符<'0' 且长度为1 则不是数字 异常
if (len == 1) // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
i++;
}
multmin = limit / radix;
// 遍历字符串转为的字符数组,将每一个字符转为10进制值,并拼接,比如输入“123” 10进制数
while (i < len) {
//获取字符转换成对应进制的整数,如上,这里第一次循环获取1
//第二次循环获取2
//第三次循环获取3
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
//判断,在追加后一个数字前,判断其是否能能够在继续追加数字,比如multmin = 123
那么再继续追加就会变为123*10+下一个数字,就会溢出
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
//第一次循环 result = 0;
//第二次循环 result = -10;
//第三次循环 result = -120;
result *= radix;
//用于判断下一个准备追加的数字是否可以追加,比如result现在是120,那么,如果digit是5,
那么追加后就会变为125,已经超过123的限制了,注意这里是limit而不是multmin
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
/第一次循环 result = -1;
//第二次循环 result = -12;
//第三次循环 result = -123;
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
//negative 值为false,所以 -result = -(-123) = 123 返回结果
return negative ? result : -result;
}
这个方法用于对指定参数的字符串转换为指定进制的数字。
7.valueOf(String s, int radix)
public static Integer valueOf(String s, int radix) throws NumberFormatException {
//字符串转化为数字
return Integer.valueOf(parseInt(s,radix));
}
public static Integer valueOf(int i) {
//如果返回的值在缓存中,直接获取缓存中数据
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
//不在则新建一个对象
return new Integer(i);
}
//初始化缓存
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;
//获取jvm配置的上限大小
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
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);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
//循环存放缓存数据
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
这个方法用于对指定参数的字符串转换为指定进制的数字对象,当中部分数据会中缓存中获取,不用新建对象。
8.byteValue()
public byte byteValue() {
return (byte)value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return value;
}
public long longValue() {
return (long)value;
}
public float floatValue() {
return (float)value;
}
public double doubleValue() {
return (double)value;
}
整型对象转化基本数据类型。
9.hashCode()
@Override
public int hashCode() {
return Integer.hashCode(value);
}
public static int hashCode(int value) {
return value;
}
重写hashcode直接返回对象的基本数据类型的值。
10.equals(Object obj)
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
重写equals,比较对象为Integer对象并且值相等即对象相等。其他方法就不一一分析了,有些比较简单,有些使用场景不多,有兴趣的可以读者自己去看看。
今天的文章JDK源码解读第八章:java.lang.Integer分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16821.html