目录
基本数据类型包装类
Byte源码研读
toString()源码研读
基本数据类型包装类
所谓万事万物皆对象,所以其实我们的基本数据类型也有针对性类的描述
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 stubByte 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 iterationwhile (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);返回一个字符串,这样就传入一个字节,返回一个字符串