目录
基本数据类型包装类
所谓万事万物皆对象,所以其实我们的基本数据类型也有针对性类的描述
byte-Byte
short-Short
int-Integer
long-Long
float-Float
double-Double
char-Character
boolean-Boolean
这些类的基类都是Number
Byte源码研读
----------------toString()源码研读
package Integer;
public class IntegerDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Byte b=new Byte("123");
byte m=7;
System.out.println(b.toString(m));
}
}
我们先来看Byte类中的toString方法
我们进入到Byte类的源码中找到这个toString()的源码,找到toString()的方法
public static String toString(byte b) {
return Integer.toString((int)b, 10);
}
这个方法它是返回的Integer中的toString()方法,再去切到Integer类中toString()方法看下
public static String toString(int i, int radix) {
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;
/* Use the faster version */
if (radix == 10) {
return toString(i);
}
char buf[] = new char[33];
boolean negative = (i < 0);
int charPos = 32;
if (!negative) {
i = -i;
}
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i = i / radix;
}
buf[charPos] = digits[-i];
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (33 - charPos));
}
因为我们的radix==10,代表的就是10进制, 通过这个if(radix==10){return toString(i)},我们看到如果是十进制,返回的是toStirng()这个方法,我们再切进去看下这个方法
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);
}
切进来我们看到,因为我们的i==7,所以size的值等于这个stringSize(i),我们再切进stringSize(i)里面看下
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
进来我们看到只有x值小于等于sizeTable[i],就会返回i+1,我们的x值是7,来看下sizeTable[i]是多少,i是从0开始的
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
因为我们的x==7<sizeTable[0]==9,所以size==i+1==1, 然后就是建立一个char [] buf =new char[size],建立一个长度为1的字符数组,
然后在进入到getChars(i.size,buf)方法里面,此时i==7,size==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
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==7,所以我们会进入这个代码块中
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;
}
进入for循环,这是匪夷所思的代码:
q = (i * 52429) >>> (16+3);
这个(i * 52429) >>> (16+3)到底是想干什么?
右移16+3也就是右移19位,也就是除以2的19次方,2的19次方=524288,所以
(i * 52429) >>> (16+3)
= (i * 52429) / 2的19次方
= (i * 52429) / 524288
= i * (52429 / 524288)
= i * 0.1000003814697266
= i * 0.1
这个0.1000003814697266的精度已经很多了,就几乎等于0.1。
所以算了这么多,这行代码其实就是q = i / 10,还是为了避免乘除法,提高运算效率。
所以q=7/10==0
至于为什么选择2的19次方524288,是因为52429/524288得到的数字精度在不超出整形范围内,精度是最高的。
如果选择2的17次方131072,那么13108 / 131072 = 0.100006103515625,
或者选择2的18次方262144,那么26215 / 262144 = 0.1000022888183594,
或者选择2的20次方1048576,那么104858 / 1048576 = 0.1000003814697266,
所得到的精度都不可能更高了。
然后下面的代码就很清楚了:
r = i - ((q << 3) + (q << 1));
意思就是r = i-(q*10),也就是r等于i除以10得到的余数。
所以r=7
然后再到buf [--charPos] = digits [r];这段代码,我们先来看下digis这个数组
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'
};
因为charPos==1,所以buf[--charPos]==buf[0]=digits[7]==7,buf数组存的数值就是字符7,然后再把i=q,就是把0给i,当i等于0时,程序结束,最终return new String(buf, true);返回一个字符串,这样就传入一个字节,返回一个字符串